什么是微前端
微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署。
为什么需要微前端
- 拆分细化 当前前端的项目通常以spa的形态出现,即一个应用所有的相关页面都在一个项目里面。随着项目的不断迭代,维护成本也会越来越高,很容易出现“牵一发而动全身”的窘境。微前端的意义在于拆分项目,细化为若干个可以单独部署的子项目,子项目互相独立,可以单独部署。
- 兼容技术栈 在传统的前端开发中,技术栈不兼容也是一个头疼的问题,我们经常会因为技术栈不兼容而做出让步。而在微前端的结构下,不同技术栈的子项目可以和谐共存
- 减小迁移成本 微前端的另一个优势,就是可以低成本地整合已有项目。因为子项目是独立的,因此不需要太大的工作量,就可以将已有的项目迁移至新的项目
什么是qiankun(乾坤)
qiankun是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
首先让我们了解一下什么是single-spa。
single-spa
single-spa是一个用于前端微服务化的JavaScript前端解决方案, 也是最早的微前端整合方案。
single-spa的原理简单的说就是,single-spa将子应用也看做一个spa的页面。主应用通过路由匹配的方式,加载并显示不同的子应用资源,子应用会经过下载(loaded)、初始化(initialized)、被挂载(mounted)、卸载(unmounted)和unloaded(被移除)等过程。single-spa会通过“生命周期”为这些过程提供钩子函数。
再说回乾坤,乾坤是基于single-spa的二次开发,它在 single-spa 基础上添加更多的功能,并且做了不错的封装,大大降低了入门微前端的门槛。
用qiankun实现微前端
官方的文档里提供了教程 qiankun.umijs.org/zh/guide/ge…
基座改造
1.安装qiankun
yarn add qiankun 或者 npm i qiankun -S
2.注册微应用
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'react app', // app name registered
entry: '//localhost:7100',
container: '#yourContainer',
activeRule: '/yourActiveRule',
},
{
name: 'vue app',
entry: { scripts: ['//localhost:7100/main.js'] },
container: '#yourContainer2',
activeRule: '/yourActiveRule2',
},
]);
start();
registerMicroApps用于注册微应用信息,当基座的路由和activeRule匹配的时候,基座就会从entry处获取微应用,并渲染到container上,同时调用微应用的生命周期。
如果微应用的加载不是根据路由匹配,也可以选择手动加载微应用
import { loadMicroApp } from 'qiankun';
loadMicroApp({
name: 'app',
entry: '//localhost:7100',
container: '#yourContainer',
});
RegistrableApp
-
name -
string- 必选,微应用的名称,微应用之间必须确保唯一。 -
entry -
string | { scripts?: string[]; styles?: string[]; html?: string }- 必选,微应用的入口。 -
container -
string | HTMLElement- 必选,微应用的容器节点的选择器或者 Element 实例。如container: '#root'或container: document.querySelector('#root')。 -
activeRule -
string | (location: Location) => boolean | Array<string | (location: Location) => boolean>- 必选,微应用的激活规则。 -
loader -
(loading: boolean) => void- 可选,loading 状态发生变化时会调用的方法。 -
props -
object- 可选,主应用需要传递给微应用的数据。
微应用改造
导出钩子函数
微应用无需安装依赖,主要改造目的是将微应用的入门“暴露”出来。
在自己的入口文件导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用调用。
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'antd/dist/antd.css';
import './public_path';
import i18n from 'i18next';
//将渲染过程封装,以便使用
function render(props: any) {
const { container } = props;
ReactDOM.render(
<React.StrictMode>
<App></App>
</React.StrictMode>,
container
? container.querySelector('#root')
: document.querySelector('#root')
);
}
//如果不是被基座加载,则正常渲染
if (!(window as any).__POWERED_BY_QIANKUN__) {
render({});
}
//bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
//通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
export async function bootstrap() {
console.log('react app bootstraped');
}
//应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法,以及监听基座传递的消息
export async function mount(props: any) {
console.log('props from main framework', props);
render(props);
props.onGlobalStateChange((state: any, prev: any) => {
console.log('子应用监听',state,prev);
});
}
export async function unmount(props: any) {
const { container } = props;
ReactDOM.unmountComponentAtNode(
container
? container.querySelector('#root')
: document.querySelector('#root')
);
}
export async function update(props: any) {
console.log('update props', props);
}
修改webpack配置
修改webpack是为了在打包的时候,能让基座正确识别微应用暴露出来的一些信息。
在webpack中添加以下配置
const packageName = require('./package.json').name;
module.exports = {
output: {
library: `${packageName}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${packageName}`,
},
};
(注:如果是webpack5,jsonpFunction 改为 chunkLoadingGlobal)
配置公共目录
src中新增public_path.js,并在入口引入
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
路由改造
乾坤是根据路由规则来选择微应用的,微应用的路由需要加上activeRule配置的路由,否则无法正确匹配微应用的路由
<BrowserRouter basename="/react-qiankun-micro">
源码分享
到这一步,一个基本的qiankun微应用的壳子就搭出来了,我在这个基础上做了一个简单的框架,效果如图,希望能对大家有帮助
react微应用:github.com/yuzhuohao/r… react主应用:github.com/yuzhuohao/r…