这两天研究了下qiankun
这个微前端实现,正好写了两个项目用的是umi且是父子应用关系,之前的方式是在主应用添加iframe
将子应用引进来,现在想通过改造成qiankun
来将两个应用联系起来,顺便试试这个库。
事先说明父应用umi版本为2.9.0
,子应用umi版本为2.10.0
。
具体操作是父子应用均通过yarn add @umijs/plugin-qiankun
添加qiankun插件,package.json
没有name
字段的需加上,父应用.umirc.ts
添加如下:
const config:IConfig = {
...,
routes: [
...,
{
path, '/app' // 这里是子应用的路由
}
],
plugins: [
...,
[
'@umijs/plugin-qiankun',
{
master: {
apps: [
{
name: 'app',
entry: '//localhost:9090',
base: '/app',
history: 'browser',
mountElementId: 'root-slave', // 注意这里是子应用要挂载在父应用上的节点id
}
],
jsSandBox: true,
prefetch: true,
}
}
]
],
proxy: {} // 如果是开发模式记得配置代理调用子应用服务端
}
配置完成后可以来到根组件下例如layout/index.tsx
下<div>{props.children}<div id='root-slave'></div></div>
,其中root-slave
的div就是子应用将要挂载的节点,这点很关键,如果没有的话将会提示Uncaught (in promise) Error: Target container is not a DOM element.
之类的报错,还有一种方式是新建一个子应用组件,例如pages/subAppContainer.tsx
组件,然后:
import React from 'react';
export default () => {
return (
<div id='root-slave'></div>
)
}
这个时候.umirc.ts
中routes里面应该添加component
:
{
path: '/app', component: './subAppContainer'
}
配置app.ts
,添加子应用生命周期函数:
export const qiankun = new Promise(resolve => {
resolve({
lifeCycles: {
beforeLoad: props => {
console.log('beforeLoad:', props);
},
beforeMount: props => {
console.log('beforeMont:', props);
},
afterMount: props => {
console.log('afterMount:', props);
},
beforeUnmount: props => {
console.log('beforeUnmount:', props);
},
afterUnmount: props => {
console.log('afterUmount:', props);
},
},
});
});
至此主应用就配置的差不多了,接下来配置子应用
添加pages/document.ejs
将根节点id修改为app-slave
或者其他啥名字,配置.umirc.js
:
export default {
...,
plugins: [
...,
[
'@umijs/plugin-qiankun/slave',
{
// 如果有其他配置请参照https://github.com/umijs/umi-plugin-qiankun里面进行配置
},
base: '/app',
mountElementId: 'app-slave' // 与`document.ejs`的根节点id保持一致
]
]
}
此前子应用的服务端前缀为/api
,为了避免与主应用冲突,将子应用服务端前缀改为/app/api
。
如此此次改造基本完成,过程中碰到的最大问题就是子应用的挂载问题,如果碰到其他问题也可以去umi的仓库提issue。