微前端的目的和 《微服务架构设计模式》中,服务端解决的命题类似。意在解决前端团队在大型项目之中,多团队、多项目、多技术栈协同带来的研发效能和成本问题。但要明白:「软件工程没有银弹」,微前端也只是学习微服务的一种架构风格,一般不要盲从去做业务改造,得想清楚收益之后再做渐进式改造。
微前端框架的设计关注点
- 协议层:描述微前端主应用和子应用或者其它 Parts 的标准,以便于多团队协作。
- 协议层关注微前端应用的 Manifest 设计
- 最基础的要素包含:
{
// 描述应用(模块)本身的类型
type: 'hostApp',
// 产物的物理地址(Artifact)
assets: {
entry: 'https://bla.bla.index.html'
},
// 访问权限控制(配合客户端和 Host 容器使用)
permissions: {
jsapi: [],
},
// ... 业务定义的描述属性,比如
i18n: 'en_US',
// ...
}
- 框架层
- 应用结构设计:找到应用之间的关系,设计合理有效的部件关系
- 主应用 or 宿主应用(主模块) HostApp & Module
- 微应用 MicroApp & SubModule & Extension & … 等等
- 加载器设计:需要一层
manifest
的标准设计,解析和执行- MicroAppLoader:微应用加载器
- ModuleLoader:模块加载器(NPM Pkg)
- IoCLoader:纯脚本,Provided Service 的脚本 see 深入浅出前端做控制反转与依赖注入
- …
- 沙箱系统设计
- JS Sandbox
- CSS Sandbox
- 管控系统设计
- AuthControl:免登和权限管控
- HostAppMetrix:宿主应用监控和指标分析
- MicroAppMetrix:微应用监控和指标分析
- …
- 应用结构设计:找到应用之间的关系,设计合理有效的部件关系
- 管控层
- 一般由平台承接
- 应用(主应用和微应用)的生命周期管理
- 应用的统计和监控维度(管控视角)
- 灰度、降级等管控机制实现
- 一般由平台承接
- 研发层
- 微应用和主应用的研发流程:DevOPS 流程,一般公司内部有研发基础设施支撑
- 业务结构化的研发流程:连接业务属性,比如业务提供的配置化导航接入微前端实践
- 工具、SDK、服务、平台,不同粒度的研发支撑
主流微前端框架
Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently. — Micro Frontends
- Technology Agnostic
- Independent Development and Deployment
- Incremental Upgrade
- Isolated Runtime
Why not iframe.
QianKun
- Simple: Works with any javascript framework. Build your micro-frontend system just like using with iframe, but not iframe actually.
- Complete: Includes almost all the basic capabilities required to build a micro-frontend system, such as style isolation, js sandbox, preloading, and so on.
- Production Ready: Had been extensively tested and polished by a large number of online applications both inside and outside of Ant Financial, the robustness is trustworthy.
Values
- solve legency system problem (contradictions between legancy system and firece new tech stack existed together)
- solve multi-team corporation problem
- solve fast delivery problem
Core features
- 📦 Based On single-spa
- 📱 Technology Agnostic
- 💪 HTML Entry Access Mode
- 🛡 Style Isolation
- 🧳 JS Sandbox
- ⚡ Prefetch Assets
- 🔌 Umi Plugin Integration
Core API
- Route based configurations
- registerMicroApps
- start
- setDefaultMountApps
- runAfterFirstMounted
- Maually load micro applications
- loadMicroApp
- prefetchApps
- addErrorHandler / removeErrorHandler
- addGlobalUncaughtErrorHandler / removeGlobalUncaughtErrorHandler
- initGlobalState: init global state, and return actions for communication. It is recommended to use in master, and slave get actions through props。
Source code analysis
Questions:
Q: How to implement style-isolation? (Runtime isolation)
ShadowDOM
Q: How to implement js-sandbox? (Runtime isolation)
Window objects clone and proxy during life-cycle of an app.
2021年01月11日 补充:
最近 Figma 实现了利用社区的 Duktape,一个由 C++ 实现的用于嵌入式设备的 JavaScript 解释器,它不支持任何浏览器 API,自然地它可以被编译到 WebAssembly,Figma 团队将 Duktape 嵌入到 Realm 上下文中,插件最终通过 Duktape 解释执行。这样可以安全的实现插件所需 API,且不用担心插件会通过原型链访问到沙箱外部。这样就可以直接收敛对外透出的 API 控制,非常适合做 JSAPI 纯沙箱 —— 这样的方案还是比较激进的!
详细可以参考:这里 这篇文章对大型 Web 应用插件化的一些思考。
Q: How to implement master-slave pattern in micro-frontend services? Communication pattern?
Event dispatcher.
Single-spa
Qiankun 整体基于该库构建。该库实现了对应用的注册、生命周期管理、路由管理映射等功能。
- 生命周期管理,本质上是一个
StateMachine
提供了life-cycle
的管理
Icestark
icestark 与 single-spa 都属于微前端的解决方案,两者在能力上并无太大差别。
icestark 内部维护了所有子应用的配置信息,包括路由规则、bundle 地址等,同时劫持了 window.history 相关的几个跳转事件,当捕获到页面跳转事件时,icestark 会根据跳转的路由获取对应的子应用信息,然后跟之前的子应用信息进行对比,如果是同一个子应用,则什么都不做,如果是不同的子应用,则将前一个子应用的 bundle 卸载,同时加载新的子应用 bundle 资源,加载完成后子应用 bundle 会执行自身的渲染逻辑。
Q & D
Q: What is the weakness or cons when we use MicroFrontEnds architecture?
- do harm to harmony of the same design conception while by injecting different tech-stack and implementations
- slightly influence the performance of app for extra bootstrap and scripts loading
Ref
- single-spa:社区公认的主流方案,可以基于它做二次开发
- qiankun:基于 single-spa 封装,增加 umi 特色,增加沙箱机制(JS、ShadowDOM 等)
- icestark:类似于 single-spa 实现,React 技术栈友好,阿里的另一个轮子
- micro-frontends awesome list