Open lei4519 opened 5 months ago
2022-11-11
React
X.Y.Z (16.1.0)
X.Y.Z
X
Y
Z
16.1.0
~X.Y.Z
16.1.9
16.1.99
^X.Y.Z
Y.Z
16.9.9
16.99.99
*
模块联邦实现了运行时的语义化版本管理,在指定的范围内尽量用高的版本
模块联邦
资源复用 & 资源隔离
模块联邦 &(iframe、qiankun、MicroApp..)
独立运行 | 独立开发 | 独立升级 | 独立部署
尽量避免各个模块间的耦合关系,保持独立。
Q: 你所了解的微前端子模块一般都是如何划分的?有什么建议? A: 我的 PPT 里有一页其实提到了,微前端拆分其实需要有明确的服务边界划分。如果你的微应用之间存在了过多的交互或者耦合,那你可能就要考虑是不是拆分的粒度过细了。 有一个简单的判断方式,就是看你的 微应用在独立打开的情况下,是否能完成一个独立 功能/服务 的提交,如果不是的,那可能就要看看了。
Q: 你所了解的微前端子模块一般都是如何划分的?有什么建议?
A: 我的 PPT 里有一页其实提到了,微前端拆分其实需要有明确的服务边界划分。如果你的微应用之间存在了过多的交互或者耦合,那你可能就要考虑是不是拆分的粒度过细了。
有一个简单的判断方式,就是看你的 微应用在独立打开的情况下,是否能完成一个独立 功能/服务 的提交,如果不是的,那可能就要看看了。
模块联邦完全相反,其功能就是模块间共享依赖,让模块与模块之间可以相互调用。
会有什么问题?
简单说:耦合越多,独立运行、独立开发、独立升级、独立部署 就越难完成()
模块联邦:依赖共享,跨模块调用,会有什么问题?
依赖版本冲突风险示例
远程模块冲突风险示例
模块提供方,不能假设使用方是完全按照规矩去使用模块的。
具有调用关系(输入输出)的多项目共享模块,必须进行版本控制(npm 包)
调用
资源(css/js)加载、组合 (共享)、执行
公用类名、tailwind
clearfix
mt-8
ellipsis
/* A */ .inactive { color: #ddd; } /* B */ .inactive { display: none; } :global { .ant-menu .ant-menu-item-selected { border-right: none; border-left: 3px solid; } .ant-menu-inline .ant-menu-item::after { border-right: none; } }
如果事情有变坏的可能,不管这种可能性有多小,它总会发生 - 墨菲定律
X.Y.Z (16.1.1)
~: 接受 Z 的最新版本
~
^: 接受 Y.Z 的最新版本
^
经过测试的版本,受其他模块影响,在线上运行时被动态升级。
new ModuleFederationPlugin({ shared: { ...dependencies, react: { singleton: true }, "react-dom": { singleton: true }, }, })
import React, { useState } from "react" import ReactDOM from "react-dom" function App() { useState() } ReactDOM.render(React.createElement(App))
module.exports = { plugins: [ new ModuleFederationPlugin({ shared: { react: { /** * 一些库使用全局内部状态(例如 react、react-dom)。 * 因此,一次只运行一个库的实例至关重要。 */ singleton: true, }, }, }), ], }
进行模块拆分、复用,模块相互之间具备调用关系
进行模块组合、引入
表格对比:
详细的介绍如下:
开发流程:多个团队在同一个代码库里开发,构建时只需要拿这一份代码去部署。
行为:开发、构建、运行一体
适用场景:单一团队,依赖库少、业务单一
开发流程:多个团队在不同的代码库里开发,在构建时将不同代码库的代码整合到一起,再去构建这个应用。
适用场景:多团队,依赖库少、业务单一
变体 - 构建时集成:开发分离,构建时集成,运行一体
开发流程:多个团队在不同的代码库里开发,在构建时将编译成不同的几份代码,运行时会通过懒加载合并到一起。
变体 - 构建后集成:开发分离,构建分离,运行一体
开发流程:多个团队在不同的代码库里开发,在构建时将编译成不同的几个应用,运行时通过主工程加载。
适用场景:多团队,依赖库多、业务复杂
前端微服务化:开发、构建、运行分离
总体的对比如下表所示:
前置 - 模块联邦实现思路
如何复用?
React
语义化版本
X.Y.Z
(16.1.0)X
:做了不兼容的 API 修改Y
:做了向下兼容的功能性新增Z
:做了向下兼容的问题修正X.Y.Z
: 指定版本,严格匹配(16.1.0
)~X.Y.Z
: 接受Z
的最新版本(16.1.0
、16.1.9
、16.1.99
)^X.Y.Z
: 接受Y.Z
的最新版本(16.1.0
、16.9.9
、16.99.99
)*
: 接受最新版本模块联邦实现了运行时的语义化版本管理,在指定的范围内尽量用高的版本
模块联邦
资源复用 & 资源隔离
模块联邦 &(iframe、qiankun、MicroApp..)
常见微前端观点
独立运行 | 独立开发 | 独立升级 | 独立部署
尽量避免各个模块间的耦合关系,保持独立。
https://micro-frontends.org/
qiankun(微前端)快问快答
模块联邦概念
模块联邦完全相反,其功能就是模块间共享依赖,让模块与模块之间可以相互调用。
会有什么问题?
简单说:耦合越多,独立运行、独立开发、独立升级、独立部署 就越难完成()
模块联邦:依赖共享,跨模块调用,会有什么问题?
依赖版本冲突风险示例
远程模块冲突风险示例
模块提供方,不能假设使用方是完全按照规矩去使用模块的。
具有调用关系(输入输出)的多项目共享模块,必须进行版本控制(npm 包)
趋势
前端 - 组件化 ✅
后端 - 微服务化 ✅
微前端化 ❓
服务器
调用
浏览器
资源(css/js)加载、组合 (共享)、执行
共用执行环境
JS 冲突
CSS 冲突
公用类名、tailwind
clearfix
、mt-8
、ellipsis
难以排查、复现
资源加载
生产依赖
依赖复用
React
语义化版本
X.Y.Z
(16.1.1)X
:做了不兼容的 API 修改Y
:做了向下兼容的功能性新增Z
:做了向下兼容的问题修正~
: 接受Z
的最新版本^
: 接受Y.Z
的最新版本如何保证所有的依赖都遵循了版本语义化?
双刃剑 - 独立部署
经过测试的版本,受其他模块影响,在线上运行时被动态升级。
模块联邦共享依赖
非法 Hook 调用
复用
不复用 - 全面隔离
可控(可信赖)的项目中 - 模块联邦复用
进行模块拆分、复用,模块相互之间具备调用关系
不可控(无信赖)的项目中 - 全面隔离
进行模块组合、引入
MicroApp
微前端的那些事儿
表格对比:
详细的介绍如下:
标准 LazyLoad
开发流程:多个团队在同一个代码库里开发,构建时只需要拿这一份代码去部署。
行为:开发、构建、运行一体
适用场景:单一团队,依赖库少、业务单一
LazyLoad 变体 1:构建时集成
开发流程:多个团队在不同的代码库里开发,在构建时将不同代码库的代码整合到一起,再去构建这个应用。
适用场景:多团队,依赖库少、业务单一
变体 - 构建时集成:开发分离,构建时集成,运行一体
LazyLoad 变体 2:构建后集成
开发流程:多个团队在不同的代码库里开发,在构建时将编译成不同的几份代码,运行时会通过懒加载合并到一起。
适用场景:多团队,依赖库少、业务单一
变体 - 构建后集成:开发分离,构建分离,运行一体
前端微服务化
开发流程:多个团队在不同的代码库里开发,在构建时将编译成不同的几个应用,运行时通过主工程加载。
适用场景:多团队,依赖库多、业务复杂
前端微服务化:开发、构建、运行分离
总对比
总体的对比如下表所示: