目录

微前端qiankun的实际应用

微前端qiankun的实际应用

https://i-blog.csdnimg.cn/blog_migrate/85243524ff38fa00a764e2fa39bfcfc4.png

微前端:微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署。

原来系统中嵌套各个模块,每个业务模块相对独立,各有独立的业务体系,单个模块体积较大,项目整体采用SPA + iframe的架构模式,其中的工单系统就是通过iframe嵌套的。在客服业务不断迭代的过程中,SPA + iframe的架构模式暴露出了很多问题

  1. 业务问题:
  • 问题一:SPA架构模式下,由于各个模块集中于一个架构下,导致首屏加载资源过多,首屏加载速度较慢;SPA只有入口文件,所以需要对各个模块做业务模式兼容,导致入口文件代码条件语句较多,代码紊乱,出现线上问题的时候,排查较为困难,如果有新的同学参与开发,梳理业务也较为困难,甚至有的时候难以理解。
  • 问题二:项目中嵌套大量的iframe,iframe也会拖累页面的加载速度,iframe使用postMessage通讯时也会带来数据延迟,数据丢失等各种问题,客服使用时间较长的时候,当切换iframe中的页面时,前一个页面中的无法被完全释放,导致浏览器所占的内存不停的飙升,最终导致浏览器崩溃。
  1. 微前端优点:
  • 技术栈无关

    主框架不限制接入应用的技术栈,微应用具备完全自主权

  • 独立开发、独立部署

    微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新

  • 增量升级

    在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略

  • 独立运行时

    每个微应用之间状态隔离,运行时状态不共享

  1. 主要挑战
  • 性能问题: 如果不同的微前端应用使用了不同的库或框架,可能会导致加载和运行的性能问题。
  • 一致性: 保持不同的微前端应用在用户体验、设计和行为上的一致性可能会比较困难。
  • 状态共享: 在微前端应用之间共享状态可能会比较复杂,需要使用特殊的工具或模式。
  • 复杂性: 尽管微前端可以解决大型项目的复杂性问题,但是它自身也带来了一些复杂性,比如需要管理和协调多个独立的应用。
  • 安全性: 微前端架构可能会增加跨域等安全问题。

1)singleSPA(国外)

国外主流框架,也是较早的一款微前端框架

  • 实现思路
    • 预先注册子应用(激活路由、子应用资源、生命周期函数)
    • 监听路由的变化,匹配到了激活的路由则加载子应用资源,顺序调用生命周期函数并最终渲染到容器
  • 缺点
    • 对微应用的入侵太强,将整个微应用打包为一个js文件,常见的打包优化基本没了,比如按需加载,首屏资源加载等
    • css和js隔离靠约束规范,很容易造成污染
    • 通信困难

2)qiankun 方案(蚂蚁)

基于single-SPA封装,进行了一些优化完善,提供了很多开包即用的API

  • 优点
    • 降低了应用改造的成本,通过html entry的方式引入子应用;
    • 提供了完备的沙箱方案,包括js沙箱和css沙箱;
    • 支持静态资源预加载能力。(start 函数接收一个可选的配置对象作为参数,prefetch:true,即在主应用 start 之后即刻开始预加载所有子应用的静态资源)
    • 应用间通信简单,全局注入
  • 缺点
    • 适配成本较高,包括工程化、生命周期、静态资源路径、路由等方面的适配;
    • css沙箱的严格隔离可能引发问题,js沙箱在某些场景下执行性能下降;
    • 无法同时激活多个子应用,不支持子应用保活;
    • 不支持vite等esmodule脚本运行。

3)micro-app 方案(京东)

实现方案:

  • 优点
    • 使用 webcomponent 加载子应用,更优雅;
    • 复用经过大量项目验证过的 qiankun 沙箱机制,提高了框架的可靠性;
    • 支持子应用保活;
    • 降低了子应用改造的成本,提供了静态资源预加载能力。
  • 缺点
    • 接入成本虽然降低,但路由依然存在依赖;
    • 多应用激活后无法保持各子应用的路由状态,刷新后全部丢失;
    • css 沙箱无法完全隔离,js 沙箱做全局变量查找缓存,性能有所优化;
    • 支持 vite 运行,但必须使用 plugin 改造子应用,且 js 代码没办法做沙箱隔离;
    • 对于不支持 webcomponent 的浏览器没有做降级处理。

5)无界方案(腾讯)

起因:在qiankun的issue有个开发者提出能否利用iframe来实现js沙箱

  • 实现方案:
    • JS沙箱:将子应用的js注入主应用ifream中运行,有着天然js沙箱
    • 路由同步:路由通过劫持ifream的history.pushState和history.replaceState,就可以将子应用的url同步到主应用的query参数上,当刷新浏览器初始化iframe时,读回子应用的url并使用iframe的history.replaceState进行同步,浏览器刷新、前进、后退都可以作用到子应用
    • css 沙箱:webcomponent机制,建一个wujie自定义元素,然后将子应用的完整结构渲染在内部
    • 通信机制:子应用所在的ifream和主应用是同域,即可以使用localStorage、window.parent等,也可以通过props注入、EventBus实例
  • 优点
    • 基于 webcomponent 容器和 iframe 沙箱,充分解决了适配成本、样式隔离、运行性能、页面白屏、子应用通信、子应用保活、多应用激活、vite框架支持、应用共享等问题。
  • 缺点
    • 社区支持可能较少

待解决的问题:

  • 微应用需要具备缓存(keep-alive)能力,应用切换状态不能丢失

    qiankun为我们提供了两个注册方法:registerMicroApps(路由改变会帮我们自动注册微应用和销毁上一个微应用,对于不需要缓存的应用简单易用),loadMicroApp(手动 加载/卸载 一个微应用)。

    loadMicroApp :在基座和微应用设置合适keep-alive缓存策略,然后通过“display: none”的方式去控制切换的显示和隐藏(DOM重新渲染会导致历史状态丢失),在基座中为每个微应用设置挂载点,应用切换的时候就不会导致前一个微应用DOM被卸载。

    结论 :1.微应用初始化加载的时候,需要经历一次资源请求,页面渲染,会有一次大的性能开销;2.微应用加载成功之后,在此切换回来,采用“display: none”+keep-alive方式处理+路由过滤,虽然需要经历一次重流重绘,但也不会带来太大的性能开销(经过前后对比得知)。

  • 需要具备同一时刻加载多个微应用

  • 沙箱隔离和引入第三方资源

  • 基座-微应用,微应用-微应用之间如何进行通讯

  • 如何接入远程组件

    远程组件采用webpack5模块联邦去实现,需要将入口文件(mian.ts)转移到新的文件(bootstrap.ts),并在入口文件中导出qiankun生命周期,避免打包出两个入口文件,导致qiankun加载生命周期函数失败。

  • 样式隔离

    官方提供的API:sandbox(boolean)

    默认场景sandbox: true , 只能保证单实例下的样式隔离,无法保证多个微应用共存,基座-微应用之间的样式隔离;

    strictStyleIsolation: true ;表示开启严格的样式隔离模式。这种模式下 qiankun 会为每个微应用的容器包裹上一个 shadow dom 节点,从而确保微应用的样式不会对全局造成影响;

感想和收益:

过程艰难曲折,第一个难关就是微应用缓存能力的实现,社区中只有简短的demo,距离真正落地到项目差的还很远;其次我们的项目还需要考虑刷新页面,在当前微应用重载其他微应用的场景;有些微应用需要依赖第三方的插件,这个插件可能会是一个jQuery插件,可能还会遇到jsonp跨域的场景;还需要考虑微应用之间通用组件的复用问题;原始项目采用vite构建,面对qiankun对vite支持不友好的情况下,最终不得不选择webpack5。

任何技术框架都有其适用场景,对于特定的业务场景,可能原来的技术架构显得臃肿,但他可能是最合适的,微前端不是神话,正确的场景使用正确的技术才是最优选。

  1. localStoragesessionStorage

    有人说这个方案必须主应用和子应用是同一个域名下。其实不是的,子应用使用不同的域名也是可以的,因为在 qiankun 中,主应用是通过 fetch 来拉取子应用的模板,然后渲染在主应用的 dom 上的,说白了还是运行在主应用上,所以还是运行在同一个域名上,也就是主应用的域名。

  2. 路由参数

    因为只有一个 url,不管子应用还是主应用给 url 上拼接一些参数,那么父子应用都可以通过 route 来获取到。

  3. Actions 通信(官方提供,比较适合业务划分清晰,应用间通信较少的微前端应用场景)

    • 这种通信方式主要通过 setGlobalState 设置 globalState,并通过 onGlobalStateChange 和 offGlobalStateChange 来注册和取消 观察者 函数,从而实现通信。

    • qiankun 内部提供了 initGlobalState 方法用于注册 MicroAppStateActions 实例用于通信,该实例有三个方法,分别是:

      • setGlobalState :设置 globalState - 设置新的值时,内部将执行 浅检查,如果检查到 globalState 发生改变则触发通知,通知到所有的 观察者 函数。
      • onGlobalStateChange :注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。
      • offGlobalStateChange :取消 观察者 函数 - 该实例不再响应 globalState 变化。
  4. Shared 通信

    • 主应用基于 redux (或别的状态管理库) 维护一个状态池,通过 shared 实例暴露一些方法给子应用使用。同时,子应用需要单独维护一份 shared 实例,在独立运行时使用自身的 shared 实例,在嵌入主应用时使用主应用的 shared 实例,这样就可以保证在使用和表现上的一致性

      1、在主应用中维护一个公共状态池,暴露set、get方法,在定义子应用的时候通过 props 传递给子应用

      2、子应用接受prop,并在自己代码库中维护一套相同的空状态池(目的是为了可以独立运行)

      3、子应用调用方法获取修改。

  • 应用加载:qiankun 通过动态创建 script 标签的方式加载子应用的入口文件。加载完成后,会执行子应用暴露出的生命周期函数。
  • 生命周期管理:qiankun 要求每个子应用都需要暴露出 bootstrap、mount 和 unmount 三个生命周期函数。bootstrap 函数在应用加载时被调用,mount 函数在应用启动时被调用,unmount 函数在应用卸载时被调用。
  • 沙箱隔离:qiankun 通过 Proxy 对象创建了一个 JavaScript 沙箱,用于隔离子应用的全局变量,防止子应用之间的全局变量污染。
  • 样式隔离:qiankun 通过动态添加和移除样式标签的方式实现了样式隔离。当子应用启动时,会动态添加子应用的样式标签,当子应用卸载时,会移除子应用的样式标签。
  • 通信机制:qiankun 提供了一个全局的通信机制,允许子应用之间进行通信。

在使用 qiankun 时,如何处理 js 沙箱不能解决的 js 污染问题?

  • 提高应用安全级别 js沙箱是保护微前端应用免受外部恶意攻击的重要手段之一。因此,我们可以提高应用的安全级别,以减少可能存在的漏洞和被攻击的风险。

  • 使用CDN等资源加速服务 在使用第三方库时,我们可以考虑使用CDN等资源加速服务来加载这些库,并优先选择官方或可信赖的CDN。这样可以减少非法脚本注入的可能性。

  • 对于自己编写的代码,需要注意以下几点:

    • 避免使用eval()函数。
    • 避免使用Function构造函数。
    • 避免使用with语句。
    • 避免在全局作用域中定义不必要的变量和函数。
  • 使用CSP(Content Security Policy) CSP是一个HTTP头,它可以让开发者指定网页中可以执行哪些类型的代码。CSP可以限制页面上的JavaScript代码只能够从特定的源加载,并且可以防止页面中注入恶意脚本。因此,我们可以使用CSP来增强应用的安全性。

  • 可以使用js-xss等XSS过滤器来过滤用户输入的HTML和JavaScript代码,以避免XSS攻击。

  1. url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
  2. UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中…
  3. 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
  4. 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程

JS entry :子应用将资源打成一个 entry script,比如 single-spa 的 example 中的方式。但这个方案的限制也颇多,如要求子应用的所有资源打包到一个 js bundle 里,包括 css、图片等资源。除了打出来的包可能体积庞大之外的问题之外,资源的并行加载等特性也无法利用上。

HTML entry :将子应用打出来 HTML 作为入口,主框架可以通过 fetch html 的方式获取子应用的静态资源,同时将 HTML document 作为子节点塞到主框架的容器中。这样不仅可以极大的减少主应用的接入成本,子应用的开发方式及打包方式基本上也不需要调整,而且可以天然的解决子应用之间样式隔离的问题。

https://i-blog.csdnimg.cn/blog_migrate/df85bd74921d2fbda232ff8a65cf46f5.png

html entry内部是通过import-html-entry包实现的。

  • 加载 HTML 入口文件:import-html-entry 会通过创建一个 标签来加载子应用的 HTML 入口文件。这样可以确保子应用的资源得到正确加载,并在加载完成后进行处理。
  • 解析 HTML 入口文件:一旦 HTML 入口文件加载完成,import-html-entry 将解析该文件的内容,提取出子应用的 JavaScript 和 CSS 资源的 URL。
  • 动态加载 JavaScript 和 CSS 资源:import-html-entry 使用动态创建 <script><link> 标签的方式,按照正确的顺序加载子应用的 JavaScript 和 CSS 资源。
  • 创建沙箱环境:在加载子应用的 JavaScript 资源时,import-html-entry 会创建一个沙箱环境(sandbox),用于隔离子应用的全局变量和运行环境,防止子应用之间的冲突和污染。
  • 返回子应用的入口模块:最后,import-html-entry 返回一个可以加载子应用的 JavaScript 模块。这个模块通常是一个包含子应用初始化代码的函数,可以在主应用中调用以加载和启动子应用。

通过使用 qiankun import-html-entry,开发者可以方便地将子应用的 HTML 入口文件作为模块加载,并获得一个可以加载和启动子应用的函数,简化了子应用的加载和集成过程。

优点:

  • 复杂度可控: 业务模块解耦,避免代码过大,保持较低的复杂度,便于维护与开发效率。
  • 独立开发,独立部署: 模块部署,减少模块影响范围,单个模块发生错误,不影响全局,提升项目稳定性。
  • 技术选型灵活: 在同一项目下可以使用市面上所有前端技术栈,也包括未来的前端技术栈。
  • 扩展性,提升业务动态扩展的可能,避免资源浪费

缺点:

  • 复杂性:微前端需要使用复杂的技术和工具来实现,需要考虑到不同子应用程序之间的通信和交互,这会增加开发和维护的复杂性。
  • 性能问题:由于微前端需要在运行时加载和卸载模块,因此可能会影响应用程序的性能。
  • 安全问题:由于微前端允许在同一个页面上共存不同的子应用程序,因此可能会带来安全隐患,需要进行严格的安全控制。微前端架构可能会增加跨域等安全问题。
  1. qiankun和ifream对比
  • qiankun 是基于 single-spa 的微前端解决方案,它通过 JavaScript 的 import 功能动态加载子应用,然后在主应用的 DOM 中挂载子应用的 DOM。qiankun 提供了一种 JavaScript 沙箱机制,可以隔离子应用的全局变量,防止子应用之间的全局变量污染。此外,qiankun 还提供了一种样式隔离机制,可以防止子应用的 CSS 影响其他应用。这些特性使得 qiankun 在处理复杂的微前端场景时具有很高的灵活性。
  • iframe 是一种较为传统的前端技术,它可以在一个独立的窗口中加载一个 HTML 页面。iframe 本身就是一种天然的沙箱,它可以完全隔离子应用的 JavaScript 和 CSS,防止子应用之间的相互影响。然而,iframe 的这种隔离性也是它的缺点,因为它使得主应用和子应用之间的通信变得困难。此外,iframe 还有一些其他的问题,比如性能问题、SEO 问题等。

在选择 qiankun 和 iframe 时,需要根据具体的使用场景来决定。如果你的子应用是基于现代前端框架(如 React、Vue、Angular 等)开发的单页应用,那么 qiankun 可能是一个更好的选择,因为它可以提供更好的用户体验和更高的开发效率。如果你的子应用是基于 jQuery 或者其他传统技术开发的多页应用,或者你需要在子应用中加载一些第三方的页面,那么 iframe 可能是一个更好的选择,因为它可以提供更强的隔离性。

  1. ifream优点
  • 代码重用性高;
  • 提高页面性能;
  • 可以跨域访问,可以在主网页和嵌套网页之间进行跨域通信
  1. 缺点
  • 安全性问题,恶意网站可能会通过 iframe 标签加载用户的敏感信息,导致信息泄露或盗取。
  • SEO 不友好
  • url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
  • 难以控制样式,例如:滚动条难以处理,屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中
  • 通信困难,目前只能使用路由、postMessage
  • 阻塞window.onload()触发,iframe加载完毕后才会触发window.onload事件,动态设置src可解决这个问题。
  • 性能开销,每个 <iframe> 都需要加载独立的HTML文档,这可能会增加页面的加载时间和网络请求数量,从而导致性能开销。
  • 样式和脚本需要额外链入,调用外部页面,需要额外调用css,增加页面额外的请求次数,增加服务器的http请求

不要过多使用ifream?

  • iframe会阻塞主页面的onload事件
  • iframe和主页面共享连接池,会影响页面的并行加载。
  • iframes阻塞页面加载,影响网页加载速度
  1. 应用场景
  • 所见即所得的网页编辑器
  • 跨域通信。JavaScript跨域总结与解决办法 ,类似的还有浏览器多页面通信,比如音乐播放器,用户如果打开了多个tab页,应该只有一个在播放
  • 用iframe实现无刷新文件上传,在FormData不可用时作为替代方案
  • 用来加载广告,例如联盟广告
  • 需要独立样式和带有交互的内容,例如幻灯片
  • sandbox沙箱隔离

在使用 qiankun 时,如果子应用是基于 jQuery 的多页应用,静态资源的加载问题可能会成为一个挑战。这是因为在微前端环境中,子应用的静态资源路径可能需要进行特殊处理才能正确加载。这里有几种可能的解决方案:

  • 方案一:使用公共路径

    在子应用的静态资源路径前添加公共路径前缀。例如,如果子应用的静态资源存放在 http://localhost:8080/static/,那么可以在所有的静态资源路径前添加这个前缀。

  • 方案二:劫持标签插入函数

    • 对于 HTML 中已有的 img/audio/video 等标签,qiankun 支持重写 getTemplate 函数,可以将入口文件 index.html 中的静态资源路径替换掉。

      🌰:传递一个 getTemplate 函数,将图片的相对路径转为绝对路径,它会在处理模板时使用

    • 对于动态插入的 img/audio/video 等标签,劫持 appendChild、innerHTML、insertBefore 等事件,将资源的相对路径替换成绝对路径。

      🌰:对于动态插入的标签,劫持其插入 DOM 的函数,注入前缀。

// qiankun 的 start 函数是用来启动微前端应用的。在注册完所有的子应用之后,我们需要调用 start 函数来启动微前端应用。
start({
  getTemplate(tpl,...rest) {
   // 为了直接看到效果,所以写死了,实际中需要用正则匹配
  	return tpl.replace('<img src="./img/jQuery1.png">', '<img src="http://localhost:3333/img/jQuery1.png">');
  }
})
beforeMount: app => {
  if(app.name === 'purehtml'){
     // jQuery 的 html 方法是一个挺复杂的函数,这里只是为了看效果,简写了
     $.prototype.html = function(value){
        const str = value.replace('<img src="/img/jQuery2.png">', '<img src="http://localhost:3333/img/jQuery2.png">')
        this[0].innerHTML = str;
     }
  }
}

在 qiankun 中,实现 keep-alive 的需求有一定的挑战性。这是因为 qiankun 的设计理念是在子应用卸载时,将环境还原到子应用加载前的状态,以防止子应用对全局环境造成污染。这种设计理念与 keep-alive 的需求是相悖的,因为 keep-alive 需要保留子应用的状态,而不是在子应用卸载时将其状态清除。

  • 方案1:在子应用的生命周期函数中保存和恢复子应用的状态。例如,我们可以在子应用的 unmount 函数中保存子应用的状态,然后在 mount 函数中恢复这个状态

    缺点 :需要手动保存和恢复子应用的状态,这可能会增加开发的复杂性。此外,这种方法也不能保留子应用的 DOM 状态,只能保留 JavaScript 的状态。

  • 方案2:手动 *loadMicroApp*+display:none ,直接隐藏Dom

  • 方案3:可以在父应用中维护一个子应用的缓存列表,然后,在切换微应用时,我们可以判断当前微应用是否需要进行缓存。如果需要,则将其标记为已缓存,并将其DOM元素从页面中移除,以便下次使用时直接显示缓存的结果;否则,直接卸载该微应用。(可能会导致内存泄漏,因此需要谨慎使用)

将每个子项目作为一个独立的应用进行开发和调试。每个子项目都可以在本地启动,并通过修改主应用的配置,让主应用去加载本地正在运行的子应用,这样就可以对子应用进行调试了。这种方式的好处是,子应用与主应用解耦,可以独立进行开发和调试,不会相互影响。

使用 npm-run-all 这个工具去启动多个项目

  • 如果 主项目使用 history 模式 ,并且子项目可以使用 history 或 hash 模式,这是 qiankun 推荐的一种形式。在这种情况下,子项目可以选择适合自己的路由模式,而且对于已有的子项目不需要做太多修改。但是子项目之间的跳转需要通过父项目的 router 对象或原生的 history 对象进行
  • 如果 主项目和所有子项目都采用 hash 模式 ,可以有两种做法:
    • 使用 path 来区分子项目:这种方式不需要对子项目进行修改,但所有项目之间的跳转需要借助原生的 history 对象。
    • 使用 hash 来区分子项目:这种方式可以通过自定义 activeRule 来实现,但需要对子项目进行一定的修改,将子项目的路由加上前缀。这样的话,项目之间的跳转可以直接使用各自的 router 对象或 。
  • 如果 主项目采用 hash 模式 ,而子项目中有些采用 history 模式,这种情况下,子项目间的跳转只能借助原生的 history 对象,而不使用子项目自己的 router 对象。对于子项目,可以选择使用 path 或 hash 来区分不同的子项目。

微应用何时被激活完全取决于你的 activeRule 配置,如下配置reactApp和react15App就会同时被mount

registerMicroApps([
  // 自定义 activeRule
  { name: 'reactApp', entry: '//localhost:7100', container, activeRule: () => isReactApp() },
  { name: 'react15App', entry: '//localhost:7102', container, activeRule: () => isReactApp() },
]);
  1. 子应用的网络请求都是在自身域名下请求的

    使用 html entry 将子应用打包成一个 html 文件,然后通过主应用中的一个 iframe 来加载这个 html 文件,这样子应用中所有的请求都会通过主应用的域名来访问,避免了跨域问题

// 主应用引入子应用
import { loadMicroApp } from 'qiankun';

loadMicroApp({
  name: 'subapp',
  entry: '//localhost:7100',
  container: '#subapp-container',
  htmlEntry: '/subapp.html',
});
  1. 当主应用和子应用不在同一个域下

    • 在子应用的服务器端配置CORS

    • 在开发环境中,可以配置前端代理,将子应用的请求代理到相应的服务器,以避免跨域。

    • 在生产环境中,可以使用Nginx反向代理,将请求从主应用代理到子应用。

      例如,主应用在 A 服务器,微应用在 B 服务器,使用路径 /app1 来区分微应用,即 A 服务器上所有 /app1 开头的请求都转发到 B 服务器上

      /app1/ {

      proxy_pass

      proxy_set_header Host

      h o s t : host:

      h

      os

      t

      : server_port;

      }

    • 通过postMessage API,主应用和子应用可以在不同域名间进行安全的跨域通信。

    • 对于静态资源(如图片、CSS、JavaScript 文件等),可以在子应用服务器端配置CORS头部信息,允许跨域访问。

  1. 路由匹配

    Qiankun 使用基于路由的机制来实现子应用的按需加载。只有当用户访问特定路由时,才会加载对应的子应用。通过配置主应用和子应用的路由规则,可以实现对子应用的按需加载。

  2. 子应用注册

    在主应用中,可以通过 registerMicroApps 方法注册多个子应用,并为每个子应用指定匹配路由、加载函数和生命周期钩子。只有当路由匹配时,才会触发子应用的加载。

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:7100',
    container: '#container',
    activeRule: '/app1',
  },
  {
    name: 'app2',
    entry: '//localhost:7101',
    container: '#container',
    activeRule: '/app2',
  },
]);

// 启动 qiankun
start();

在上面的例子中,app1 和 app2 是两个子应用,分别配置了它们的入口、渲染容器和激活规则。当用户访问 /app1 路径时,app1 会被加载并渲染到指定容器中,而 app2 则在访问 /app2 路径时被加载。

  1. 动态加载资源

    Qiankun 会在路由匹配时,动态地通过 HTTP 请求加载子应用的资源(如 HTML、JavaScript、CSS 文件等)。加载完毕后,Qiankun 会将这些资源注入到主应用的 DOM 中。

  2. 沙箱机制

    Qiankun 提供了沙箱机制,确保子应用在独立的上下文中运行,不影响其他子应用或主应用。沙箱机制配合按需加载,可以确保子应用的资源和状态在进入和离开时得到正确的处理。

  3. 生命周期钩子

    Qiankun 提供了一系列生命周期钩子(如 beforeLoad、beforeMount、afterMount、beforeUnmount、afterUnmount 等),在子应用加载和卸载的过程中,可以在这些钩子中执行特定的逻辑,如资源初始化、数据预处理、资源清理等。

在qiankun中,子应用需要导出三个生命周期函数:

  • bootstrap:子应用初始化时调用,只会调用一次;

  • mount:子应用挂载时调用,可能会调用多次;

  • unmount:子应用卸载时调用,可能会调用多次;

    https://i-blog.csdnimg.cn/blog_migrate/7db940ffbc1714cc4bb9eb15221874ff.png