【WuJie-腾讯无界微前端】

无界微前端实现方式

  1. 使用前端技术Shadow DOM(影子 DOM),iframe, Custom element(自定义元素),实现微前端渲染子应用的css隔离和js隔离
  2. iframe使用new Blob() 加 URL.createObjectURL()创建一个blob:的伪同源的iframe
  3. React,Vue等三方框架使用WuJie提供的对应框架的组件,借助相应的生命周期钩子实现子应用加载。
  4. jsp等非前端框架需手动调用WuJie API实现子应用加载
  5. 借助Proxy,Object.defineProperties实现对document,location,ownerDocument,baseURI等属性的代理,将shadow dom 与 iframe 与 主应用上下文关联起来。

无界实现简单流程图
简化流程图

无界微前端方案要解决的问题

  1. iframe内嵌的子应用如何保证能够使用主应用上下文中的cookie等信息?
    浏览器的请求大致分为两类,静态资源请求和网络请求。
    因为wujie需要对js的逻辑执行进行代理,所以需要将静态资源的请求转变成网络请求的方式来获取响应体text【第二个问题有提到】。所以wujie暴露了fetch让使用者可以配置跨域请求的自定义函数,以保证请求的静态资源url与当前域名不同源(same-origin)时能够让请求体带有cookie这个请求头。
    在这里插入图片描述
    在这里插入图片描述
    对于网络请求能不能携带cookie这个请求头是同理的。而对于子应用发起的请求能不能携带主应用下的cookie信息,我的理解是这样子的。只要这个请求满足cookie信息配置的Domain,Path等规则,就能够通过携带,与发起位置,怎样发起并无关系。

    总结来看要注意两点:
    第一点:请求能不能带有cookie这个请求头,与当前请求url,当前源,服务端跨域配置等有关系
    第二点:请求头中cookie中能不能携带某一个cookie信息,与当前请求的url和具体cookie信息的配置设置有关系

  2. wujie如何能够保证子应用内部能够正确使用location.protocol + ‘//’ + location.host拼接跳转的正确性?
    wujie在创建过程中使用proxy代理子应用的window,location等,然后将代码执行时的location替换为代理后的proxyLocation对象,从而实现对子应用location的劫持,来返回子应用正确的location信息。
    在这里插入图片描述
    在这里插入图片描述
    但是从wujie的逻辑来看,只有内联脚本,非降级并且是非type=‘module’的才能触发这段逻辑。那其它不满足这个判断的怎么办呢???

  3. 即然iframe和shadow dom是分开的,那么无界是如何将两者关联起来的?
    首先,如何将iframe中js执行逻辑中对dom的操作映射到shadow dom。
    对iframe的Document.prototype进行劫持,以下为本地测试劫持Doucment.prototpe.append属性,所实现的效果
    在这里插入图片描述
    劫持Docuemnt.prototype,然后将执行函数的this指向shadow,就与创建的shadow串联起来了。
    在这里插入图片描述
    在这里插入图片描述
    但是存在一个问题,iframe到shadow方向的通道打通了,那shadow到iframe的呢。比如原生html或者jsp中最喜欢写的onclick的原生绑定事件,能不能在shadow中指向iframe的window呢???

  4. shadow dom如何保证相对或者绝对路径资源访问的正确性?
    iframe对js中出现的资源访问路径采用了多种处理方式,来保证最终资源请求的正确星
    第一种:
    创建base标签,设置正确指向的href属性,添加到frame中的head标签中
    在这里插入图片描述
    第二种:
    对创建iframe中的HTMLImageElement.prototype的属性进行代理,下面是我本地简单代理 HTMLImageElement.prototype的src属性所实现的效果。
    在这里插入图片描述
    wujie关键逻辑:对HTMLImageElement.prototype的src属性通过Object.prototype进行劫持,然后通过iframe正确设置的baseUrl来将路径替换成完整的url资源路径
    在这里插入图片描述
    在这里插入图片描述

在使用 wujie 微前端框架时,如果主项目是基于 Vue2 技术栈,而子项目是基于 Vue3 并使用了 TSX 编写页面内容,可能会遇到子项目代码修改后页面未更新的问题。这一问题通常与资源加载机制、缓存策略或子项目的构建配置有关。 ### 1. 检查子项目的构建配置 确保子项目输出的资源格式符合微前端的要求。在使用 Vite 构建子项目时,需要将输出格式设置为 `UMD`,以便兼容沙箱环境,并确保入口文件正确暴露微前端生命周期钩子。例如,在 `vite.config.ts` 文件中配置如下内容: ```ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import baseConfig from '../../shared-config/vite.base.config'; export default defineConfig({ ...baseConfig, build: { target: 'es2020', format: 'umd', // 微前端要求子应用输出 UMD 格式(兼容沙箱环境) entry: './src/micro.ts', // 暴露微前端生命周期钩子的入口 manifest: true, // 生成资源清单供基座动态加载 rollupOptions: { external: ['react', 'react-dom'], // 外置基座已提供的依赖 output: { name: 'subReactApp', // UMD 全局变量名(避免冲突) globals: { react: 'React', 'react-dom': 'ReactDOM', }, }, }, }, plugins: [ ...baseConfig.plugins, react(), // 使用 React 插件处理 TSX 文件 ], }); ``` 上述配置确保了子项目能够正确输出 UMD 格式的资源,并且使用了 `react` 插件来处理 TSX 文件。如果子项目没有正确配置这些选项,可能会导致资源加载失败或页面内容无法更新。 ### 2. 确保子项目资源正确加载 在微前端架构中,主项目需要动态加载子项目的资源。为了确保子项目能够正确加载并更新页面内容,需要检查以下几点: - **资源路径是否正确**:确保子项目的资源路径(如 JS、CSS 文件)在主项目中能够正确访问。 - **资源缓存问题**:浏览器可能会缓存子项目的资源文件,导致修改后的内容无法生效。可以通过在资源路径中添加版本号或时间戳来避免缓存问题。例如: ```html <script src="sub-app.js?v=1.0.1"></script> ``` ### 3. 检查微前端沙箱环境的隔离机制 wujie 微前端框架通过沙箱环境实现 JS 和 CSS 的隔离。如果子项目的 JS 或 CSS 被沙箱环境拦截,可能会导致页面内容无法更新。可以通过以下方式排查: - **JS 隔离**:wujie 使用 `window` 工厂模式实现 JS 隔离。确保子项目中的全局变量不会与主项目冲突,并且正确使用沙箱环境提供的 API。 - **CSS 隔离**:wujie 支持类似 Vue 的 `scoped` 样式隔离方案。确保子项目的样式不会影响到主项目,并且样式文件能够正确加载。 ### 4. 启用热更新功能 在开发环境中,可以启用热更新功能,以便在子项目代码修改后自动刷新页面。Vite 提供了热更新支持,可以通过以下配置启用: ```ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [ react(), // 启用 React 插件 ], server: { hmr: { overlay: false, // 关闭 HMR 覆盖层 }, }, }); ``` 确保主项目和子项目都启用了热更新功能,并且网络请求能够正确触发页面刷新。 ### 5. 检查子项目的生命周期钩子 在微前端架构中,子项目的生命周期钩子(如 `bootstrap`, `mount`, `unmount`)需要正确实现。如果这些钩子函数没有正确执行,可能会导致子项目无法正确加载或更新。例如: ```ts // src/micro.ts import { createApp } from 'vue'; import App from './App.vue'; let app: any; export async function bootstrap() { console.log('子项目启动'); } export async function mount() { console.log('子项目挂载'); app = createApp(App); app.mount('#app'); } export async function unmount() { console.log('子项目卸载'); app.unmount(); } ``` 确保 `mount` 和 `unmount` 钩子能够正确执行,并且在卸载时释放所有资源。 ### 6. 调试工具的使用 可以使用浏览器的开发者工具进行调试,查看子项目的资源是否成功加载,以及控制台是否有错误信息。重点关注以下几点: - **网络请求**:检查子项目的 JS、CSS 文件是否成功加载。 - **控制台日志**:查看子项目的生命周期钩子是否执行,以及是否有错误提示。 - **DOM 结构**:确认子项目的页面内容是否正确渲染到指定的容器中。 通过以上步骤,可以逐步排查并解决 wujie 微前端框架中 Vue2 主项目加载 Vue3 子项目时页面未更新的问题。如果问题仍然存在,建议检查主项目和子项目的依赖版本是否兼容,并确保所有配置文件正确无误 [^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值