写点什么

开源一夏 | Qiankun 框架对于微前端的解耦和沙盒与实战探索心得

作者:黎燃
  • 2022 年 8 月 24 日
    内蒙古
  • 本文字数:2500 字

    阅读完需:约 8 分钟

qiankun 框架


由于主应用程序和微应用程序可以独立于技术堆栈,所以 qiankun 只是一个面向用户的类似 jQuery 的库。需要调用几个 API 来完成应用程序的微前端转换。同时,由于 qiankunHTML 入口和沙盒的设计,微应用程序的访问与使用 iframe 一样简单。

解耦

微前端的核心目标是将巨石应用程序分解为几个松散耦合的、可以自主的微应用程序,而乾坤的许多设计都遵循这一原则,例如 HTML 输入、沙盒和应用程序间通信。只有这样,才能确保微应用真正具有自主开发和自主运行的能力。

微应用信息注册

微应用信息注册后,一旦浏览器 URL 发生变化,将自动触发 qiankun 的匹配逻辑。所有与 activerule 规则匹配的微应用程序将被插入到指定的容器中,并依次调用微应用程序公开的生命周期钩子。


$ yarn add qiankun # 或者 npm i qiankun -S
复制代码


如果微应用程序与路由没有直接关联,还可以选择手动加载微应用程序:


import { loadMicroApp } from 'qiankun';
loadMicroApp({ name: 'app', entry: '//localhost:7100', container: '#yourContainer',});
复制代码

微应用

1.微应用分为网页包构建和非网页包构建项目。使用 webpack 的微应用程序(主要是 Vue、react 和 angular)需要执行以下操作:


注意:运行时的 publicpath 和构建时的 publippath 是不同的,不能等价地替换它们。


2.微应用程序建议使用历史模式路由。需要设置路由基础。该值与其 activerule 相同。3.引入公共路径。js 在条目文件的顶部,修改和导出三个生命周期函数。4.修改 webpack 打包以允许跨域和 UMD 打包开发环境。


主要修改为上述四项,可能会根据项目的不同情况而变化。例如,项目是索引 HTML,所有其他文件都是单独部署的。这意味着在构建时已将 publicpath 设置为完整路径。运行时不需要修改 publicpath(可以保存第一步)。


添加公共路径。SRC 目录中的 js:


if (window.__POWERED_BY_QIANKUN__) {  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;}
复制代码


设置历史模式路由的基础:


<BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/app-react' : '/'}>
复制代码


这个条目是 JS 的文件索引。为了避免根 ID#root 与其他 DOM 之间的冲突,需要限制搜索范围。


import './public-path';import React from 'react';import ReactDOM from 'react-dom';import App from './App';
function render(props) { const { container } = props; ReactDOM.render(<App />, container ? container.querySelector('#root') : document.querySelector('#root'));}
if (!window.__POWERED_BY_QIANKUN__) { render({});}
export async function bootstrap() { console.log('[react16] react app bootstraped');}
export async function mount(props) { console.log('[react16] props from main framework', props); render(props);}
export async function unmount(props) { const { container } = props; ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));}
复制代码

非 webpack 构建的微应用

一些非 webpack 构建的项目,如 jQuery 项目和 JSP 项目,可以根据此进行处理。


<script src="//yourhost/entry.js" entry></script>
复制代码


在访问之前,请确保项目中的图片、音频和视频资源能够正常加载。如果这些资源的地址是完整路径(例如https://qiankun.umijs.org/logo.png)是的,很好。如果它们是相对路径,则需要首先将这些资源上载到服务器并使用完整路径。在 entry js 里声明 lifecycles:


((global) => {  global['purehtml'] = {    bootstrap: () => {      console.log('purehtml bootstrap');      return Promise.resolve();    },    mount: () => {      console.log('purehtml mount');      return render($);    },    unmount: () => {      console.log('purehtml unmount');      return Promise.resolve();    },  };})(window);
复制代码


访问非常简单。只需要声明一个脚本来导出相应的生命周期。


const packageName = require('./package.json').name;
复制代码


除了在代码中暴露相应的生命周期钩子之外,为了使主应用程序能够正确识别微应用程序暴露的一些信息,微应用程序的打包工具需要添加以下配置:


module.exports = {  output: {    library: `${packageName}-[name]`,    libraryTarget: 'umd',    jsonpFunction: `webpackJsonp_${packageName}`,  },};
复制代码

实现思路

1.预加载资源如果在应用程序注册配置中存在需要预加载的应用程序,则应在初始化的同时加载这些应用程序。初始化路由根据配置的路由规则匹配当前页面路径,并查找当前有效的应用程序信息。popstate 监控页面路由变化,并根据路由变化获取当前有效应用 3.代理一些窗口事件。由于每个应用程序可能会绑定一些窗口事件,因此它会劫持窗口 Addeventlistener,后者记录每个应用程序绑定的事件,以便在以后切换路由时清除这些事件。4.加载资源目标页面,分析各种资源,然后加载并执行 5.在每个应用程序执行之前记录全局变量,记录当前全局变量,然后在卸载应用程序时清除所有全局变量,以避免影响下一个应用程序的执行。

qiankun 沙盒模型

我们知道所有全局方法、全局变量/常量和全局对象都属于窗口对象,这些全局方法和对象可能会造成 JS 污染。它可以在加载子系统之前创建窗口对象的快照(副本),然后在卸载子系统时恢复快照。也就是说,它可以确保每次子系统运行时,都是一个新的窗口对象环境。实际上,一般原则是记录子系统运行过程中添加、修改和删除的窗口对象的属性和方法,然后在卸载子系统时恢复这些操作。


应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法


export async function mount(props) {  ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));}
复制代码


应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例


export async function unmount(props) {  ReactDOM.unmountComponentAtNode(    props.container ? props.container.querySelector('#root') : document.getElementById('root'),  );}
复制代码


发布于: 刚刚阅读数: 4
用户头像

黎燃

关注

前端工程师 2022.05.06 加入

专注学习分享前端知识。

评论

发布
暂无评论
开源一夏  | Qiankun框架对于微前端的解耦和沙盒与实战探索心得_开源_黎燃_InfoQ写作社区