umijs推出的微前端框架qiankun,是国内比较流行的微前端方案,其官方文档有配置的方法,但是说的比较模糊,这里亲自实践一下

创建项目

微前端分位主应用和若干个微应用,分别独立运行。所以分别创建以下目录解构:

1
2
3
4
<project root>
|__main
|__app1
|__app2

根据umijs文档,分别在每个项目里生成对应的umijs项目,并都安装
umijs乾坤插件 @umijs/plugin-qiankun

1
2
3
4
npm i yarn tyarn -g
tyarn create @umijs/umi-app
tyarn add @umijs/plugin-qiankun
tyarn

修改.umirc配置

这个是文档没说清楚的地方,所有umijs的配置,均要在.umirc里修改,在main项目添加以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 routes: [
{
path: '/',
component: '@/pages/index',
routes: [
{
path: '/app1',
microApp: 'app1',
},
{
path: '/app2',
microApp: 'app2',
},
],
},
],
qiankun: {
master: {
// 注册子应用信息
apps: [
{
name: 'app1', // 唯一 id
entry: '//localhost:7701', // html entry
},
{
name: 'app2', // 唯一 id
entry: '//localhost:7702', // html entry
},
],
},
},

app1app2.umirc 分别写:

1
2
3
qiankun: {
slave: {},
},

app1app2package.json 分别指定app名字,否则qiankun插件认不出来:

1
2
3
4
5
// app1 package.json 
"name": "app1"

// app2 package.json
"name": "app2"

这里注意,微服务要跑在不同端口,根据在.env文件中定义,我们可在 main app1 app2 下分别创建 .env 文件并写下端口号,如:

1
2
3
4
5
6
7
8
# main
PORT=7700

# app1
PORT=7701

# app2
PORT=7702

这样,当每个项目各自跑的时候,就能按要求跑在指定的端口号

子项目配置 app.ts 文件

这个是关键一步,每个子项目都要配置对应的子项目生命周期函数,否则报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// app1/src/app.ts
export const qiankun = {
// 应用加载之前
async bootstrap(props: any) {
console.log('app1 bootstrap', props);
},
// 应用 render 之前触发
async mount(props: any) {
console.log('app1 mount', props);
},
// 应用卸载之后触发
async unmount(props: any) {
console.log('app1 unmount', props);
},
};

// app2/src/app.ts
export const qiankun = {
// 应用加载之前
async bootstrap(props: any) {
console.log('app2 bootstrap', props);
},
// 应用 render 之前触发
async mount(props: any) {
console.log('app2 mount', props);
},
// 应用卸载之后触发
async unmount(props: any) {
console.log('app2 unmount', props);
},
};

更改界面

走到这一步, app1app2 均会配置到主应用 mainprops.children里了,我们将主应用界面更改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// main/src/pages/index.tsx

import styles from './index.less';

export default function IndexPage(props) {
console.log('props----->', props.children.props.children);
return (
<div>
<h1 className={styles.title}>Main App</h1>
<div>{props.children}</div>
</div>
);
}

最终效果如下,通过/app1 可达 app1 应用,/app2可达 app2 应用:

umijs-qiankun微前端效果