微前端 qiankun

前言

环境准备

创建三个项目分别是:

其中 react 项目都是通过 create-react-app 创建的,vue 项目通过 vite 创建,另外项目还需要安装 qiankun。

搭建主应用

子应用渲染入口

首先需要给子应用在主应用中渲染的容器,我们在 App.js 中写一个容器

定义子应用的列表

在 src 下新建一个 subApp.js

  • name 子应用的名称,需要唯一
  • entry 子应用的入口,就是子应用的访问地址,这里通过环境变量来达到不同环境使用不同的入口地址
  • container 子应用在主应用的挂载的节点,就是把子应用放在主应用的哪个地方,上文我们有定义
  • activeRule 子应用路由规则,主应用触发该路由加载访问子应用

配置环境变量

新建 .env.development 文件

1
2
REACT_APP_REACT_SUB=//localhost:8080/react
REACT_APP_VUE_SUB=//localhost:5173/vue

需要注意的是一定要以 REACT_APP 开头的环境变量才会被识别。

注册子应用并启动

在入口文件 main.js 中通过 qiankun 提供的 registerMicroApps 注册我们的子应用,使用 start 启动

1
2
registerMicroApps(microApps)
start()

另外 registerMicroApps 还可以传入第二个参数 lifeCycles ,也就是全局的微应用生命周期钩子,start 也可以传入一些配置项,具体参考

react 子应用搭建

window.POWERED_BY_QIANKUN

首先需要了解一下 window.__POWERED_BY_QIANKUN__ 这个值,这是 qiankun 注入的一个全局变量,是一个布尔值,他代表了当前应用是不是在 qiankun 的容器中运行

修改 publicPath

新建一个 public-path.js 文件,需要在入口文件 index.js 中引入。

1
2
3
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

routebase

修改 App.jsx 文件,主要定义 routebase。

需要注意的是,这里的 BASE_NAME 一定要和主应用中定义的子应用列表的 activeRule 一致。

修改入口文件 index.js

  • render 就是进行渲染的方法,这里 render 限制了查找根节点的范围
  • 然后判断是在主应用下运行的还是单独运行的
  • mount 是每次进入子应用调用的钩子
  • unmount 是卸载调用的钩子

修改 webpack 配置

因为我们是用 create-react-app 创建的项目,不使用 eject 的情况下,修改 webpack 配置需要安装插件 react-app-rewired 或者 @rescripts/cli,这里我们用前者。

新建 config-overrides.js 文件

vue 子应用搭建

安装插件

vite 需要安装插件 vite-plugin-qiankun 才能使用 qiankun。

配置 vite.config.js

修改入口文件


判断是否在 qiankun 的环境下运行应用,和 react 的配置类似。

优化

完成以上步骤其实就基本实现了构建微前端项目的过程,但还有一些地方可以进行简单的优化

指定子应用的启动端口

在开发环境下,主应用需要子应用的入口,指定子应用的端口就不用每次去修改主应用的配置了,上文中 vue-sub 我在写 vite.config.js 的时候已经指定的端口为9000,react-sub 的话通过环境变量就能指定启动端口号了,在 react-sub 中新增环境变量配置文件 .env.development,声明 PORT=8080
即可

通过按钮切换两个子应用

在 react-master 的 App.js 中实现两个按钮分别切换 react-sub 和 vue-sub

这里推荐使用 window.history.pushState 让页面在不刷新的情况下进行跳转。

应用间通信

initGlobalState

首先在主应用中通过 initGlobalState API 初始化一个全局 state

1
2
3
4
5
6
7
8
9
// src/shared/actions
import { initGlobalState } from "qiankun";

const initialState = {
sharedProperty: ''
};
const actions = initGlobalState(initialState);

export default actions;

然后调用 onGlobalStateChange 来观察全局 state 的变化,当 state 发生变化时,就会调用这个函数

1
2
3
4
5
6
7
8
9
 // 注册一个观察者函数
actions.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
// 设置值
actions.setGlobalState({
sharedProperty: 'qiankun-example'
});

子应用接收 state

子应用在 render 生命周期中可以通过 props 获取主应用传来的 state

1
2
3
4
5
6
function render(props) {
if (props) {
console.log(props)
}
// ...
}

并且也可以用 actions 的方法进行操作,我们可以封装一个类来处理 state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function emptyAction() {
console.warn("Current execute action is empty!");
}

class Actions {
actions = {
onGlobalStateChange: emptyAction,
setGlobalState: emptyAction
}
setActions(actions) {
this.actions = actions;
}
onGlobalStateChange(...args) {
return this.actions.onGlobalStateChange(...args);
}
setGlobalState(...args) {
return this.actions.setGlobalState(...args);
}
}


const actions = new Actions();
export default actions;

微前端 qiankun
https://l1ushun.github.io/2024/05/22/qiankun-baics/
作者
liu shun
发布于
2024年5月22日