背景
随着React19已经是stable的状态、很快会大面积投放使用,而且带来很多便捷与先进的开发方式以及新功能、新特征为开发效率赋能,但是项目的历史版本问题也是行业共同问题
一方面想用新技术,一方面也要兼顾老项目和历史问题,特别在微前端的应用上面更为明显,目前主流的做法都是React 17、18、19三个版本同时并存来加载运行应用,确保代码能正常执行
推演
为了解决上述问题、要进一步剥离框架所带来的影响如:
- React框架以及会影响代码正常运行的附属内容
- Module Federation Runtime & SDK
- React 目前对代码的向下兼容能力比较乐观、很多老方法都保留了下来,对团队业务开发来说影响不大
- 实现 3层架构对项目的灵活度、微前端轻量化来说是最有效的方案
@empjs/share 从创建到实现经历了 3 代的迭代分别为
- [1.0] module federation shared
- [2.0] emp shared library
- [2.5] emp fast mode、emp runtime
- [3.0] empShare 实现跨框架的同时、兼容了之前所有版本的共享模型,并且收归了共享所需的所有内容
随着时间推移、目前前两代的共享模型已经处于落后的状态,不能很好做依赖共享的配置,实现跨框架共享难度大,共享管理存在黑盒子问题难以追踪
随着新技术的引入,3.0 就以上的问题已经得到很好的解决,目前存在以下几个问题(优先级正序):
- 类型共享存在不确定性
- Runtime 模型缺乏指导性封装与应用,需要提供系统化教程
- 需要把已打造好的案例模板化,系统化输出
EMP FastMode
EMP FastMode是我们2024年6月基于Module federation v2重新设计的新的共享模式,fastMode,进一步的把runtime、SDK从产物上剥离出来,减少框架对业务层的影响
对比起简单的Module Federation Shared,在EMP3启动项目之中,使用FastMode后能让启动项目构建后包体积减少76%
,模块索引体积减少74%
。
FastMode比传统Module Federation Shared包体积小的原因是,FastMode 提取公共依赖到EMPShareLib,并进一步把远程模块公共运行时依赖的module-federation/runtime与sdk提取出来。从而实现加载提效
当然目前 Module federation 团队也意识到这个问题、在最新版本也开始陆续解决这些问题 externalruntime
实战
EMP v3.5 & @empjs/share
文档使用参考 link
3.5 在上述基础上把 React的所有依赖也抽离业务 从而实现 业务与框架的完全分离
代码片段
import {defineConfig} from '@empjs/cli'
import pluginReact from '@empjs/plugin-react'
import {pluginRspackEmpShare} from '@empjs/share/rspack'
export default defineConfig(store => {
const reactVersion = 19
return {
plugins: [
pluginReact({
version: reactVersion,
}),
pluginRspackEmpShare({
// module federation runtime & sdk 配置 基于 0.6.10 小部分重构 支持external
empRuntime: {
runtime: {
lib: `https://yourcdn.com/@empjs/share@3.5.0/output/sdk.js`,
},
// 框架以umd格式暴露
framework: {
name: 'react',
version: reactVersion,
// 最终访问地址 默认为 reactRouter.development.umd.js
entry: 'reactRouter',
global: 'EMP_ADAPTER_REACT',
// 自动区分 dev & prod
lib: `https://yourcdn.com/@empjs/react@${reactVersion}/dist`,
},
},
}),
],
}
})
实际效果代码如下
可以clone 下来运行 emp dev
观看结果:
图中我们看到
- 导航分别代表了3个React项目,分布到17~19的版本
- 切换导航,表示独立运行到相应的版本,而且正常运行
- 中间两个是独立的远程组件
- 在微前端、低代码的业务环境中,多版本远程组件是一个必不可少的功能,方案可以很好实现
结论
通过以上方案、我们可以实现:
- 1 项目不断开展的情况下可以无缝 React的框架升级而不影响现有业务的正常运行
- 2 运行代码最小化原则,只涵盖了最基本的业务代码,服务最优选择
- 3 代码维护成本直线降低,更适合微前端的落地 (构建时候各个版本会有部分差异性代码存在,此方案很好解决这个问题)