qiankun文档: 快速上手
微前端 : 是最近一年国内前端领域被频繁提及的关键字,虽然它并不是一个全新的领域/技术,但很显然在当今越来越多的前端应用即将步入第 3 个、第 5 个甚至更久的年头的背景下,如何给 巨石应用/遗产应用 注入新鲜的技术血液已经成为我们不得不正视的问题,而微前端正是解决这类问题的一个非常合适的解决方案。
qiankun : 是一个生产可用的微前端框架,它基于 single-spa,具备 js 沙箱、样式隔离、HTML Loader、预加载 等微前端系统所需的能力。qiankun 可以用于任意 js 框架,微应用接入像嵌入一个 iframe 系统一样简单。
应用场景: 1. 主应用与多个相互独自的微应用 一起构成了整个大的微前端应用
2. 可以在同一个页面中,加载多个不同的微应用,每个微应用都是主应用的组成部分 或者是 提供一些增强能力,这种场景可以说是微应用粒度的前端组件化。
即: qiankun 相当于 route-based 的控制台应用,做为一个微应用的聚合框架而被使用。
使用步骤:
yarn add qiankun # or npm i qiankun -S
import { registerMicroApps,runAfterFirstMounted, start } from 'qiankun';
// window.qiankunStarted 为严谨,防止加载多次 (可省略)
if (!window.qiankunStarted) {
window.qiankunStarted = true;
registerMicroApps(
[
{
name: 'invoice', // 子应用名的标识
entry: `${process.env.VUE_APP_INVOICE_URL}`, // 子应用的目标地址, 可在环境变量中配置
container: '#subapp-viewport', // 把加载到的子路由界面放在某个容器中
// loader,
activeRule: '/invoice', // 加载以/invoice开头的路由
},
],
// 主应用的生命周期
// {
// beforeLoad: [
// app => {
// console.log('[LifeCycle] before load %c%s', 'color: green;', app.name);
// },
// ],
// beforeMount: [
// app => {
// console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name);
// },
// ],
// afterUnmount: [
// app => {
// console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name);
// },
// ],
// },
);
// 初始化主应用属性
// const { onGlobalStateChange, setGlobalState } = initGlobalState({
// // user: 'qiankun',
// });
// onGlobalStateChange((value, prev) => console.log('[onGlobalStateChange - master]:', value, prev));
// 设置自定义属性可传参到子应用中, 在子应用的mounted钩子中使用prop属性来接受
// setGlobalState({
// // ignore: 'master',
// // user: {
// // name: 'master',
// // },
// });
// setDefaultMountApp('/');
start();
// runAfterFirstMounted(() => {
// console.log('[MainApp] first app mounted');
// });
}
当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。
3.1. 在微应用的 src
目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
3.2. 修改微应用中的路由文件router.js
,根据微应用标识限制路由范围
3.3. 入口文件 main.js
修改,为了避免根 id #app
与其他的 DOM 冲突,需要限制查找范围。
// 在微应用中的main.js中配置
let instance = null;
function render(props = {}) {
// props对象中的container属性指的是主应用的dom
const { container } = props;
instance = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : document.querySelector('#app'));
}
// 独立运行微应用时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
// 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
export async function mount(props) {
console.log('[vue] props from main framework', props);
render(props);
}
// unmount时销毁应用, 防止内存泄漏
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
}
vue.config.js
)const { name } = require('./package');
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
output: {
library: `invoice`, // 应用标识, 和name保持一致
libraryTarget: 'window', // 把微应用打包成window格式
jsonpFunction: `webpackJsonp_${name}`,
},
},
};
使用qiankun微应用需要注意几点:
1. 在微应用src中新增 public-path.js
文件,用于修改运行时的 publicPath
2. 微应用建议使用 history
模式的路由,需要设置路由 base
,值和它的 activeRule
是一样的。
3. 在入口文件最顶部引入 public-path.js
,修改并导出三个生命周期函数。
4. 修改 webpack
打包。
主应用路由配置需要注意到的点:
1. 微应用入口路由需配置在主应用的后面. 否则主应用的界面显示不出来
2. 如遇到路由显示的顺序问题, 如上图, 第一个路由菜单需显示在左侧导航栏的最后面, 可以给每个路由设置order属性, 用于在渲染导航栏菜单之前进行排序.
3. 如遇到样式冲突, 则各自加载各自的vue和elementUI