背景:在项目开发中,有这样的需求,多个项目要通过统一的门户网站加载出来,该统一门户网站只显示相应按钮进行菜单导航切换
qiankun.js介绍:
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。参考:: 介绍-qiankun
优势
技术栈无关;独立开发、部署;增量升级;独立运行状态隔离
Why Not Iframe
使用:
主应用:主应用里调用app注册微应用,并通过star启动
安装qiankun
$ yarn add qiankun # 或者 npm i qiankun -S
在src目录新建qiankun文件夹,并在里面新建一个index.js用于编写注册微应用代码
initQiankun方法
export const initQiankun = () => {
if (!window.qiankunStarted) {
window.qiankunStarted = true
console.log('env', import.meta.env)
// console.log('store.', store.state.user)
let state = {
accessToken: '',
userInfo: {}
}
const actions = initGlobalState(state)
// 这里监听子应用传过来的数据,暂时用不到
// actions.onGlobalStateChange((state, prev) => {
// // state: 变更后的状态; prev 变更前的状态
// console.log('更改后的状态', state, prev);
// });
registerMicroApps([
{
name: 'hzzg_web_cockpit',
entry: import.meta.env.VITE_APP_hzzg_web_cockpit_url,
activeRule: 'hzzg_web_cockpit',
container: '#hzzg_web_cockpit',
props: {
userInfo: localStorage.getItem('userInfo') && (JSON.parse(localStorage.getItem('userInfo')) || {}),
accessToken: localStorage.getItem('accessToken') || '',
actions: actions
}
},
{
name: 'activity-guarantee',
entry: import.meta.env.VITE_APP_activity_guarantee,
activeRule: 'activityGuarantee',
container: '#activityGuarantee',
props: {
userInfo: localStorage.getItem('userInfo') && (JSON.parse(localStorage.getItem('userInfo')) || {}),
accessToken: localStorage.getItem('accessToken') || '',
actions: actions
}
}
]);
}
}
接口解释:
registerMicroApps(apps, lifeCycles?)
apps - Array RegistrableApp - 必选,微应用的一些注册信息
RegistrableApp
{
name: 'hzzg_web_cockpit',
entry: import.meta.env.VITE_APP_hzzg_web_cockpit_url,
activeRule: 'hzzg_web_cockpit',
container: '#hzzg_web_cockpit',
props: {
userInfo: localStorage.getItem('userInfo') && (JSON.parse(localStorage.getItem('userInfo')) || {}),
accessToken: localStorage.getItem('accessToken') || '',
actions: actions
}
},
name: 微应用的名称,微应用之间保持唯一,此name必须和微应用package.json中的name字段保持一致,见后文微应用的打包配置,output中的library取值为package.json中的name
entry: 配置为字符串时,表示微应用的访问地址
activeRule: 微应用的激活规则,直接跟 url 中的路径部分做前缀匹配,匹配成功表明当前应用会被激活。在浏览器 url 发生变化会调用 activeRule 里的规则
props:主应用要传递给微应用的数据,后面会讲到微应用如何接收数据
container:微应用的容器节点的选择器,即要把微应用挂载到主应用的哪个dom节点下
如我的主应用项目配置container: ‘#hzzg_web_cockpit’,则对应主应用app.vue中对应有di=“hzzg_web_cockpit”
<template>
<div>
<Bar v-if="isShow" />
<div id="hzzg_web_cockpit"></div>
<div id="central_big_screen"></div>
<div id="muckmanage"></div>
<div id="largeScreen"></div>
<div id="hzGgmxjtDp"></div>
<div id="linjunjie"></div>
<div id="municipal"></div>
<div id="activityGuarantee"></div>
<div id="mcsScreen"></div>
<router-view></router-view>
<Footer v-if="isShow" />
</div>
</template>
startQiankun方法,调用此方法启动qiankun
export const startQiankun = () => {
start({
singular: false,
sandbox: {
// strictStyleIsolation: true,
// experimentalStyleIsolation: true, // 开启沙箱模式,实验性方案
},})
}
方法写好后在哪里调用呢,本项目是在用户登录获取到用户信息后调用的initQiankun,然后调用startQiankun。至此,主应用的配置已经完成。
微应用
微应用的配置主要分为四步
1、在src目录新增public-path.js文件,用于修改运行时的 publicPath
public-path.js内具体代码如下:
if (window.__POWERED_BY_QIANKUN__) {
console.log('微应用启动', window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__)
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
2、在入口文件最顶部引入 public-path.js,修改并导出三个生命周期函数,主应用传递通过props传递过来的数据可以在render函数中获得const { container, accessToken, userInfo, actions } = props,userInfo和accessToken就是主应用传递过来的用户信息
import './public-path'
function render(props = {}) {
const { container, accessToken, userInfo, actions } = props;
if (window?.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-console
console.log('props', props);
}
instance = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时
if (!window?.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
// eslint-disable-next-line no-console
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
// props.setGlobalState(state);
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
// router = null;
}
3、打包配置修改(vue.config.js)
const { name } = require('./package');
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
output: {
library: name,
libraryTarget: 'umd', // 把微应用打包成 umd 库格式
jsonpFunction: `webpackJsonp_${name}`
},
},
};
实际应用中会有各种坑,附上官方各种问题解决方案qiankun.js常见问题解决方案
纸上得来终觉浅,绝知此事要躬行