# Docs重构
# 一、背景
Docs项目有以下几点主要痛点:
# 1. 巨石应用维护困难
金山文档经过多年持续不断的迭代,已经变得很庞大,项目本地打包耗时30分钟,打包后的主文件vendor.js有7M,kso-ui.js有6.3M,部署上线要耗费大半天时间,头一回遇到这种巨石应用。
# 2. 开发流程复杂
无法本地运行开发,遇到复杂需求和bug需要反复修改和反复部署,效率非常低。例如:修改kso里面的bug,改kso代码 -> 私有化(jenkins) -> kso发包 -> cloud/mobile私有化 -> 部署,整个流程走完大概2个小时。
# 二、微前端
微前端的诞生也是为了解决以上问题。
# 1. 什么是微前端
微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为 多个小型前端应用聚合为一的应用 。各个前端应用还可以 独立运行、独立开发、独立部署 。
# 2. 微前端优势
- 复杂度可控** 😗* 每一个UI业务模块由独立的前端团队开发,避免代码巨无霸,保持开发时的高速编译,保持较低的复杂度,便于维护与开发效率。
- 独立部署** 😗* 每一个模块可单独部署,颗粒度可小到单个组件的UI独立部署,不对其他模块有任何影响。
- 技术选型灵活** 😗*也是最具吸引力的,在同一项目下可以使用如今市面上所有前端技术栈vue/react/angular/jquery...
- 扩展** 😗* 每一个服务可以独立横向扩展以满足业务伸缩性。
- 容错** 😗* 单个模块发生错误,不影响全局,就跟后端微服务一样。
# 3. 微前端框架选择
调研了市面上实现微前端的框架,可供选择的有iframe、sigle-spa、qiankun和microApp (opens new window)。single-spa太过于基础,对原有项目的改造过多,成本太高,对项目的可维护性带来了挑战; iframe在所有微前端方案中是最稳定的、上手难度最低的,但它有一些无法解决的问题,例如性能低、通信复杂、双滚动条、弹窗无法全局覆盖,它的成长性不高,只适合简单的页面渲染。剩下的只有qiankun和microApp了。microApp (opens new window)是基于WebComponent进行渲染的,如果嵌入到PC客户端里兼容性有问题,最后只剩下qiankun。
# 三、qiankun
qiankun (opens new window)框架其实是基于single-spa框架搭建而成的,本质上是把 single-spa 和 import-html-entry 整合在了一起,简单来说就是single-spa的优化版。
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。 qiankun 孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台,在经过一批线上应用的充分检验及打磨后,我们将其微前端内核抽取出来并开源,希望能同时帮助社区有类似需求的系统更方便的构建自己的微前端系统,同时也希望通过社区的帮助将 qiankun 打磨的更加成熟完善。 目前 qiankun 已在蚂蚁内部服务了超过 200+ 线上应用,在易用性及完备性上,绝对是值得信赖的。 ---- 摘自 qiankun__官网介绍
# 四、qiankun实战
qiankun架构基本可以概括为: 基座应用 + 子应用 + 公共依赖方式,详细架构如下图:
# 1. 创建基座
初始化基座项目,通过vue-cli快速创建一个vue项目
vue create appmain
构建主应用基座,开始进行改造,首先安装qiankun
yarn add qiankun
安装完qiankun后,先对main.ts进行改造,针对主应用进行配置,这里我们需要定义并注册微服务应用,并添加全局状态管理与消息通知机制,apps.ts文件用于统一存放微应用的信息,微应用配置信息中的container是用于设定微应用挂载节点的,要与自己设定的节点<div id="subapp"></div>中的id保持一致。
main.ts的改造过程:
- 初始化基座应用 vue create main;
- 安装乾坤 yarn add qiankun;
- 设置微服务应用挂载的DOM节点,注意这个id需要在注册子应用时使用;
- 定义子应用 main\src\core\apps.ts;
- 改造main.ts,注册子应用并添加相关工具类函数。
接下来就是需要定义子应用,并确保定义的子应用能在当前基座应用下成功运行。
# 2. 创建微应用
接入Vue子应用app1(vue3)
vue create app1
添加vue.config.js,有两点需要注意:
- output需要设置为umd格式的library,这样主应用就可以加载当前lib并运行。
- devServe端口需要设置与注册该子应用时的端口一致, 并设置cors, 因为子应用与主应用不同域。
改造子应用的main.ts。子应用的接入需要符合qiankun的接入协议,子应用不需要额外安装任何其它依赖即可接入主应用。
其他微应用配置同上。
# 3. 项目结构
qiankunapp
├─ app1
├─ app2
├─ app3
├─ app4
├─ app5
└─ appmain
# 4. 功能演示
# 五、qiankun接入Docs
# 1. 接入要点
- 动态路由管理
使子工程之间有能力互通切换,以路由为单位把新旧模块逐步替换。
- 全局状态管理
qiankun通过initGlobalState, onGlobalStateChange, setGlobalState实现主应用的全局状态管理,然后默认会通过props将通信方法传递给子应用。官方示例用法:
主应用:
// main/src/main.js
import { initGlobalState } from 'qiankun';
// 初始化 state
const initialState = {
user: {} // 用户信息
};
const actions = initGlobalState(initialState);
actions.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();
子应用:
// 从生命周期 mount 中获取通信方法,props默认会有onGlobalStateChange和setGlobalState两个api
export function mount(props) {
props.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
props.setGlobalState(state);
}
父子应用通过onGlobalStateChange这个方法进行通信,其实是发布-订阅模式。
# 2. 技术架构
qiankun:基座nuxt.js(ssr) + 微应用vue/react
详细架构图如下:
# 3. Docs微前端
Docs微前端设计图如下: