# 1. 什么是微前端
类似于一种微服务的框架, 将微服务的理念运用于浏览器端,及将单页面前端应用由单一的单体应用转变为多个小型前端应用聚合为一的应用, 他们也可以在共享组件的同时进行并行开发 ---这些组件可以通过 npm 或者 Git tag, git submodule 来管理
# 2. 使用场景
- 项目很多,规模很大,都是每个项目独立使用 git 此类仓库维护的、技术栈为 vue/react/angular 的这类应用
- 需要整合到统一平台上,你正在寻找可能比 iframe 更合适的替代方案
- 项目 A 有功能 A1、A2、A3,项目 B 有功能 B1、B2、B3,此时需要把 A2、B1、B3 组合成一个包含这些功能的新项目
- 维护、迭代成本高,需求变更影响范围大
# 3.主应用与微应用
- 简单来讲,某平台代表主应用, 项目 A,项目 B..就是代表各个子应用。
- 主应用应该是包含了系统中的公共部分例如:菜单栏、登录、退出等功能;
- 微应用则是为满足业务需求所开发的多数子项目,需要区分的是微应用和组件的区别,组件是为了满足单一模块的功能,组件组件之间可以根据业务进行通信等,而微应用则是一个完整独立的项目,所以如果关联紧密存在频繁通信的应用应该做成一个微应用。
# 4. 场景对比
- iframe: 缺点: 结构冗余、事件通讯繁琐、只能处理视图相关服务、操作反馈复杂。。。
- single-spa.js 缺点: 只有 app 级别的隔离、没有统一的服务规范、 使用了 system.js、对业务的侵入性太强。。。
###5. 构成
解析:将公共服务放在系统核心,其他功能等放在外部服务。每个外部服务有他的 context 上下文(用来与整个系统交互),events 事件,以及 life Cycle 生命周期,manifest 签名(描述外部服务的基本行为)。 为实现系统核心和外部服务的链接,服务器需要根据当前的场景,拿到对应外部服务的 manifest 注册到系统核心,(此过程称为服务发现),在点击该服务页面时,根据 manifest 中的入口开始调起, 拿到所属服务中的 modules,之后开始调起生命周期。
# 6.single-spa 使用
# 简介
single-spa 一个基于 JavaScript 的 微前端 框架,他可以用于构建可共存的微前端应用,每个前端应用都可以用自己的框架编写,完美支持 Vue React Angular。可以实现 服务注册 事件监听 子父组件通信 等功能。
# 实现
(1) 搭建基础框架后,在父项目注册子项目
singleSpa.registerApplication
:这是注册子项目的方法。参数如下:
appName
: 子项目名称applicationOrLoadingFn
: 子项目注册函数,用户需要返回 single-spa 的生命周期对象。后面我们会介绍 single-spa 的生命周期机制activityFn
: 回调函数入参 location 对象,可以写自定义匹配路由加载规则。
singleSpa.start
:这是启动函数。
(2)子项目
- 安装具体环境的 npm 包,(如使用 vue 子项目提供 single-spa-vue),可以快速和 sigle-spa 父项目集成,并提供了一些比较便携的 api。
- 在入口文件引入 npm 包,包装一个微前端服务对象,传入挂载参数,就可以实现注册。它会返回一个对象,里面有 single-spa 需要的生命周期函数。使用 export 导出即可
(3)webpack 的处理 只是导出了,还需要挂载到 window 在项目目录下新建 config.js, 修改 webpack 配置,修改 webpack output 内的 library 和 libraryTarget 字段。
- output.library: 导出的对象名
- output.libraryTarget: 导出后要挂载到哪里
(4)独立运行 single-spa 有个属性,叫做 window.singleSpaNavigate。如果为 true,代表就是 single-spa 模式。如果 false,就可以独立渲染。
# 7. qiankun 基本使用
# qiankun 简介
- 基于 single-spa 进行二次开发, 提供了开箱即用的 API。
- 技术栈无关,任意技术栈的应用均可使用/接入,不论是 React/vue/Angular/Jquery 还是其他等框架。
- HTML Entry 接入方式, 接入微应用像使用 iframe 一样简单。
- 样式隔离, 确保微应用之间样式互不干扰。
- JS 沙箱,确保微应用之间全局变量/事件 不冲突。
- 资源预加载, 在浏览器空闲时间预加载未打开的微应用资源, 加速微应用打开速度。
- umi 插件, 提供了@umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。
# 安装、注册、应用
官网教程 (opens new window)
(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();
当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。
如果微应用不是直接跟路由关联的时候,可以选择手动加载微应用的方式:
import { loadMicroApp } from 'qiankun';
loadMicroApp(
{
name: 'app',
entry: '//localhost:7100',
container: '#yourContainer',
}
);
(3) 微应用 微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap() {
console.log('react app bootstraped');
}
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props) {
console.log(props);
ReactDOM.render(<App />, document.getElementById('react15Root'));
}
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById('react15Root'));
}