微前端之背景与实践
微前端最早于2016年在 Micro-Frontends 被提出,并建⽴了早期的微前端模型。微前端的命名和能⼒和微服务有类似之处,微服务与微前端,都是希望将某个单⼀的单体应⽤,转化为多个可以独⽴运⾏、独⽴开发、独⽴部署、独⽴维护的服务或者应⽤的聚合,从⽽满⾜业务快速变化及分布式多团队并⾏开发的需求。如康威定律(Conway’s Law)所⾔,设计系统的组织,其产⽣的设计和架构等价于组织间的沟通结构;微服务与微前端不仅仅是技术架构的变化,还包含了组织⽅式、沟通⽅式的变化。微服务与微前端原理和软件⼯程,⾯向对象设计中的原理同样相通,都是遵循单⼀职责(Single Responsibility)、关注分离(Separation of Concerns)、模块化(Modularity)与分⽽治之(Divide & Conquer)等基本的原则。
课程目标
- 微前端如何解决业务场景的痛点,以
qiankun为例接⼊微前端。 - 微前端的核⼼实现原理,从0到1实现简单的微前端框架。
知识要点
微前端的背景
微前端是什么
⼀种类似于微服务的架构,是⼀种由独⽴交付的多个前端应⽤组成整体的架构⻛格,将前端应⽤分解成⼀些更⼩、更简单的能够独⽴开发、测试、部署的应⽤,⽽在⽤户看来仍然是内聚的单个产品。
现代web应⽤⾯临的问题
DX(developer experience)
- 多个系统在⼀个仓库应⽤中,不同⼦应⽤独⽴SPA模式
- 系统分为多个仓库,独⽴上线部署,采⽤MPA模式
UX(user experience)
- 性能体验
- ⻚⾯跳转和⽤户体验问题
解决⽅案-微前端
微前端的意义
微前端的主要特点
- 低耦合:当下前端领域,单⻚⾯应⽤(SPA)是⾮常流⾏的项⽬形态之⼀,⽽随着时间的推移以及应⽤功能的丰富,单⻚应⽤变得不再单⼀⽽是越来越庞⼤也越来越难以维护,往往是改⼀处⽽动全身,由此带来的发版成本也越来越⾼。微前端的意义就是将这些庞⼤应⽤进⾏拆分,并随之解耦,每个部分可以单独进⾏维护和部署,提升效率。
- 不限技术栈:在不少的业务中,或多或少会存在⼀些历史项⽬,这些项⽬⼤多以采⽤⽼框架类似(Backbone.js,Angular.js 1)的B端管理系统为主,介于⽇常运营,这些系统需要结合到新框架中来使⽤还不能抛弃,对此我们也没有理由浪费时间和精⼒重写旧的逻辑。⽽微前端可以将这些系统进⾏整合,在基本不修改来逻辑的同时来同时兼容新⽼两套系统并⾏运⾏。
微前端解决的问题
- 业务领域的代码库不够独立和高度可重用
- 相同的产品功能由多个团队开发/产品功能难以保持统一
- 新的产品理念无法在不同的应用中快速复用/实现
- 快速迭代新子业务/干净移除将被淘汰的子业务
- 提升构建效率
- 改善交付效率
- 架构渐进升级
- 子团队的独立性
微前端的价值
微前端的方案
微前端应该具备哪些能力
⼀些可以实现微前端的⽅案
使⽤ HTTP 服务器的路由来重定向多个应⽤
在不同的框架之上设计通讯、加载机制,诸如 Single-SPA qiankun icestark
通过组合多个独⽴应⽤、组件来构建⼀个单体应⽤
- 微前端之构建时⽅案(Module Federation EMP)
iframe。使⽤ iframe 及⾃定义消息传递机制
- 使⽤纯 Web Components 构建应⽤
- 结合 Web Components 构建
业界主流的微前端框架
- single-spa :社区公认的主流⽅案,可以基于它做⼆次开发
- qiankun :基于 single-spa 封装,增加 umi 特⾊,增加沙箱机制(JS、ShadowDOM 等)
- icestark :类似于 single-spa 实现,React 技术栈友好,阿⾥的另⼀个轮⼦
基于 qiankun 的微前端实战
创建主应用基座
基坐主要实现微应⽤框架的初始化和注册等,通常没有具体的应⽤业务逻辑在⾥边
创建主应用
- 使用 React 创建主应用
1 | npx create-react-app main |
- 使用 Vue 创建主应用
1 | npm install -g @vue/cli |
创建微应用容器
在主应⽤中创建微应⽤的承载容器,这个容器规定了微应⽤的显示区域,微应⽤将在该容器内渲染并显示。
注册微应用
构建好了主框架后,需要使⽤ 的 registerMicroApps ⽅法注册微应⽤
1 | // index.js |
启动微应用
1 | // index.js |
接入微应用
qiankun 内部通过 import-entry-html 加载微应⽤,要求微应⽤需要导出⽣命周期钩⼦函数
- 导出相应的生命周期钩子
微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。
1 | /** |
- 配置微应用的打包工具
除了代码中暴露出相应的生命周期钩子之外,为了让主应用能正确识别微应用暴露出来的一些信息,微应用的打包工具需要增加如下配置:
1 | const packageName = require('./package.json').name; |
接入 Vue 微应用
接入 React 微应用
补充知识点
DIY 微前端实现核心能力
应用注册
- registerMicroApps
监听路由变化
- history
- hashHistory
生命周期
- 主应用
- beforeLoad:挂载子应用前
- mounted:挂载子应用后
- unmounted:卸载子应用
- 子应用
- bootstrap:首次应用加载触发,常用于配置子应用全局信息
- mount:应用挂载时触发,常用于渲染子应用
- unmount:用于卸载时触发,常用于销毁子应用
路由劫持
- 路由变化时匹配子应用
- 执行子应用生命周期
- 加载子应用
资源加载
- 加载样式表
- 提取 js 代码
- 执行 js 渲染
JS 沙箱
1 | export class ProxySandbox { |