這兩天研究了下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。