代码共享与应用架构
多种代码共享方式对比
要理解它,我们需要能够将它与我们迄今为止所接触到的机制进行比较。要做到这一点,我们需要设想一个相当常见的场景。你有一个企业系统,在这个系统中,你有两个应用程序;第一个是面向内部的内容管理系统(CMS
NPM 包
到目前为止,

这种方法的优势在于它的高度控制和版本化。要更新渲染组件,需要修改、批准代码并发布到
- 更新
npm 包版本 - 更新
A 管理系统应用的npm 包版本 - 发布部署
A 管理系统应用 - 对
B 和C 管理系统应用循环2 和3 步骤


微前端
在微前端(Micro-frontend,Micro-FE)模型中,渲染代码再次被提取到一个新的项目中,但代码在运行时要么在客户端,要么在服务器上使用。

为了实现这一点,

具体理解就是,我们可以把复用的业务子模块,放在同一个基站应用之中,来管理和维护,并且暴露出去可以给多个管理系统应用使用。如果业务子模块需要更新逻辑的话,只需要发布部署基站应用,其他管理系统应用并不需要做什么操作,只需要访问时刷新,就可以立即拿到最新的业务子模块逻辑了。
缺点是,就像在
另一个缺点是,对渲染代码的更新可能最终会破坏任何一个地方的应用。因此,需要增加额外的监测,以使之成为一种新的应用。这项工作。性能和代码重复是管理的挑战。由于任何一个消费者都可能 已经有
减少代码重复的一个变通方法是将常用的包外部化,由消费程序独立加载。然而,这可能会成为一个非常手动的过程,并且可能是危险的,因为有一个高度集中的依赖,常用代码总是在那里。这可能会违背
Module Federation
通过

在这种新的架构中,
该模式的优势如下:
- 代码保持原位,对于其中一个应用程序,渲染代码保持原位,不做修改。
- 无框架,只要两个应用程序使用相同的视图框架,就可以使用相同的代码。
- 没有代码加载器,
Micro-FE 框架通常与代码加载器结合在一起,比如SystemJS ,它与工程师习惯的babel 和Webpack 导入并行工作。导入联合模块的工作就像任何普通的导入一样。它只是碰巧是远程的。与其他方法不同的是,Module Federation 不需要对现有的代码库进行任何改动。没有Micro-FE 框架的学习曲线。 - 适用于任何
Javascript ,当Micro-FE 框架在UI Components 上工作时,Module Federation 可以用于任何类型的Javascript,UI Components ,业务逻辑,i18n 字符串等。任何Javascript 都可以共享。 - 适用于
Javascript 以外的内容,虽然许多框架都非常注重Javascript 方面,但Module Federation 可以处理Webpack 目前能够处理的文件,如图像、JSON 和CSS 。如果你能要求它,它就能被联邦化。 - 通用,
Module Federation 可以在任何使用Javascript 运行时的平台上使用,如浏览器、Node、Electron 或Web Worker 。它也不需要特定的模块类型。许多框架需要使用SystemJD 或UMD 。Module Federation 将与当前可用的任何类型一起工作,包括AMD 、UMD、CommonJS、SystemJS、window 变量等。
就像任何架构一样,有一些缺点,其中最主要的是链接的运行时性质。就像在
应用架构
微前端的落地,需要考虑到产品研发与发布的完整生命周期;我们会关注如何保证各个团队的独立开发与灵活的技术栈选配,如何保证代码风格、代码规范的一致性,如何合并多个独立的前端应用,如何在运行时对多个应用进行有效治理,如何保障多应用的体验一致性,如何保障个应用的可测试与可依赖性等方面。通常应用中的每个页面都有一个微前端实例,还有一个容器应用,它有以下功能:呈现常见的页面元素,如页眉和页脚;解决了身份认证和跳转等跨领域问题;在页面上集成多个微前端,并告诉各个微前端该何时何地呈现自己。
实际上所有的微前端框架都面临这两大共性问题。当你解决了这两大问题之后,你的微前端框架的运行时,就已经基本可用了。
- 应用的加载与切换。包括路由的处理、应用加载的处理和应用入口的选择。
- 应用的隔离与通信。这是应用已经加载之后面临的问题,它们包括
JS 的隔离(也就是副作用的隔离) 、样式的隔离、也包括父子应用和子子应用之间的通信问题。
具体而言,我们可能从应用组合、应用隔离、应用协调与治理、开发环境等几个方面进行考虑:
-
应用集成
: - 集成时机,在构建时组合,还是在运行时组合;是在服务端组合,还是在客户端组合;
- 应用路由,如何根据
URL 加载/ 导航到不同的页面,如何根据子应用界面的变化切换URL ; - 应用加载,确定加载应用的版本,依赖于框架的加载机制,还是采用
AMD 或者SystemJS 异步加载;
-
应用隔离
: - 应用容错,某个应用的崩溃不应影响到其他应用或容器应用;
- 样式隔离,避免
CSS 相互污染; DOM 隔离,避免子应用操作非自身作用域内的结点;
-
应用协调与治理:
- 统一配置与切换,主题,利用
CSS Variables 等方式动态换肤; - 应用的生命周期,规范化子应用的生命周期,并且在不同生命周期中执行不同的操作;
- 数据共享,子应用间数据共享,父子、子子应用间通信;
- 服务共享,跨应用数据共享与服务调用;
- 组件共享,可能将某个纯界面组件或者业务组件以插件
(Plugin) 或者部件(Widget) 的方式共享出去;提供某些业务逻辑的计算能力;
- 统一配置与切换,主题,利用
-
开发环境:
- 跨技术栈支持;
- 统一的构建流程与规范;
- 打桩、埋点与
Hijack ;
此外值得一提的是,微前端化本身是为了保证系统的持续集成与快速迭代,那么对于各个子模块与系统本身的可用性与稳定性势必会带来挑战,这就要求我们在设计微前端解决方案时,考虑持续构建的时机与对应的测试方案;除了标准的单元测试、集成测试、端到端测试之外,我们还需要保证模块的依赖一致性与功能模块的可生成性;关于此部分的详细讨论参阅