微前端基础知识入门篇(二)
# 概述
在上一篇介绍了一些微前端的基础知识,详见微前端基础知识入门篇一 (opens new window)。本文主要介绍qiankun微前端框架的实战入门内容。
# qiankun微前端实践
通过Vite脚手架分别创建三个程序,主应用A为:vite+vue3+ts,两个微应用分别为B:vite+vue3+ts;C:vite+React+ts。因为qiankun的微应用是技术无关性,因此微应用可以是一个简单网页html,也可以是任意前端框架搭建的一个网页应用。
三个应用分别安装qiankun库,终端运行如下命令:
yarn add qiankun
# 微应用的注册
在主应用A中程序入口文件src/main.ts中注册微应用如下:
import { createApp } from "vue";
import { registerMicroApps, start } from "qiankun";
import App from "./App.vue";
const app = createApp(App);
app.mount("#app");
registerMicroApps([
{
name: "B_App",
entry: "//localhost:5157",
container: "#main_container",
activeRule: "/cb",
},
{
name: "C_App",
entry: "//localhost:5158",
container: "#main_container",
activeRule: "/c",
},
]);
start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 代码分析
registerMicroApps函数
该函数是基于路由去配置微应用,其语法为:registerMicroApps(apps,lifeCycles?)。
- 参数
apps:必选,微应用的注册信息,其类型为Array<ReigsterableApp>lifeCycles:可选,全局的微应用生命周期钩子,其类型为LifeCycles
- 类型
RegisterableApp:一个对象,其属性如下:name:必选,微应用名称且唯一entry:必选,微应用入口,可以是字符,表示微应用访问地址;也可以是对象,其属性html对应的就是微应用的html内容字符串container:必选,#main_container为微应用在主应用挂载的容器,可以是主应用中任意一个存在的DOM元素,且多个微应用之间也是独立的,挂载的容器自不必相同。activeRule:必选,微应用的激活规则,当主应用的地址栏url匹配到改规则时,该微应用就会被激活,其值也可以是一个函数、数组字符串或者数组函数,函数接受的参数就是当前location,函数的返回值是一个布尔值,true表示匹配成功。loader:可选,类型是一个函数接受一个布尔值,表示loading状态,当其值发生变化时,会调用该函数props:可选,类型是一个对象,可以用于主应用传递给微应用的数据
LifeCycles:生命周期集合,每个属性值都是一个函数,或者是一个数组函数,函数返回一个Promise,接受的参数是RegisterableApp类型的对象,其属性可选值分别为beforeLoad,beforeMount,afterMount,beforeUnmount和afterUnmount
start()函数 start()函数主要用于启动qiankun主应用,其参数都是可选的,如下
prefetch:是否开启微应用的静态资源预加载,默认值是true,其值可以为下面几个true:第一个微应用mountted后,开始预加载其余微应用的静态资源all:主应用start后就开始预加载所有微应用静态资源string[]:在第一个微应用mounted后开始加载数组内的微应用资源function:自定义微应用的资源加载时机
sandbox:是否开启沙箱,默认为true,其值也可以是一个对象{strictStyleIsolation:boolean,experimentalStyleIsolation:boolean},表示是否开启严格的样式隔离,默认情况下会为每个应用的容器包裹一个shadow dom节点,从而隔离样式。singular:可选,表示是否是单实例场景,即同一时间只会渲染一个微应用,默认为truefetch:用来定制请求微应用资源的方式的一个配置项。它可以用来替换默认的资源获取方式。允许开发者自定义获取微应用资源(如JS、CSS文件等)的方式getPublicPath:用来获取微应用的公共路径getTemplate:用于动态获取微应用的HTML模板excludeAssetFilter: 过滤不需要加载的静态资源,优化性能
# 微应用的改造
前面通过Vite创建了两个应用B和C,在这两个应用中分别都安装qiankun和vite-plugin-qiankun,使之成为一个微应用
# B微应用
B微应用的技术体系是vite+vue3+ts,在其配置文件vite.config.ts中引入qiankun,配置如下:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import qiankun from "vite-plugin-qiankun";
export default defineConfig({
plugins: [vue(), qiankun("vue-B-app", { useDevMode: true })],
server: {
port: 5157, //固定端口
},
});
2
3
4
5
6
7
8
9
10
第二步就是修改其入口文件main.ts,如下:
import { createApp } from "vue";
import {
renderWithQiankun,
qiankunWindow,
QiankunProps,
} from "vite-plugin-qiankun/dist/helper";
import "./style.css";
import App from "./App.vue";
const app = createApp(App);
let root:any = null;
function render(props: QiankunProps) {
const { container } = props;
const node = container
? container.querySelector("#app")
: document.getElementById("app");
console.log("🚀 ~ render ~ node:", node);
root=app.mount(node)
return root;
}
renderWithQiankun({
mount(props: any) {
root = render(props);
},
bootstrap() {},
unmount(props: any) {
console.log(props);
root?.unmount();
},
update(props: any) {
console.log(props);
},
});
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
root = render({});
}
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
32
33
34
35
36
37
38
39
40
# C微应用
C微应用的技术体系是vite+react+ts,由于都是vite搭建的,所以其改动也差不多,不同的是main.ts中render部分,如下:
function render(props: QiankunProps) {
const { container } = props;
console.log("🚀 ~ render ~ container:", container)
const node = container
? container.querySelector("#root")
: document.getElementById("root");
console.log("🚀 ~ render ~ node:", node)
root = createRoot(node!);
root.render(<App />);
return root;
}
2
3
4
5
6
7
8
9
10
11
之所以不同是因为vue3和React挂载节点方式的区别,这个render函数兼顾了各自的微应用独立运行和作为微应用运行两种方式。
# vite-plugin-qiankun插件
顾名思义,vite-plugin-qiankun插件就是为vite搭建的应用量身定制的一款插件。我们可以来分析它在上述用到的renderWithQiankun方法和qiankunWindow变量。
renderWithQiankun其实现如下:
var renderWithQiankun = function (qiankunLifeCycle) {
if (qiankunWindow === null || qiankunWindow === void 0 ? void 0 : qiankunWindow.__POWERED_BY_QIANKUN__) {
if (!window.moudleQiankunAppLifeCycles) {
window.moudleQiankunAppLifeCycles = {};
}
if (qiankunWindow.qiankunName) {
window.moudleQiankunAppLifeCycles[qiankunWindow.qiankunName] = qiankunLifeCycle;
}
}
};
2
3
4
5
6
7
8
9
10
由上可知,renderWithQiankun函数的作用就是在确认当前应用为微应用时,会将其参数挂载到全局对象window.moudleQiankunAppLifeCycles上,qiankunName就是微应用在在主应用注册时的name值。
qiankunWindowqiankunWindow本质上就是window对象,其值如下:
var qiankunWindow = typeof window !== 'undefined' ? (window.proxy || window) : {}; //代理优先级最高