三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Esmx 模块链接实战:供给方、消费方、组合方三种角色如何协作?

Esmx 模块链接实战:供给方、消费方、组合方三种角色如何协作?

Esmx 模块链接实战:供给方、消费方、组合方三种角色如何协作?

【免费下载链接】genesisNext-generation micro-frontend framework based on ESM, sandbox-free with zero runtime overhead, supporting multi-framework hybrid development项目地址: https://gitcode.com/gh_mirrors/genesis8/genesis

Esmx 是一个基于 ESM 标准的下一代微前端框架,以"无沙箱、零运行时开销、支持多框架混合开发"著称。而**模块链接(Module Linking)**正是它实现跨应用代码共享的核心能力:多个独立构建的应用之间,可以像使用本地模块一样安全地共享代码,全程不引入任何额外的运行时库。本文用最小配置带你理解模块链接中的三种协作角色——供给方、消费方、组合方,以及它们之间"接线"是如何被自动推导出来的。

一图看懂:多框架子应用如何组合成一个平台

在动手之前,先看 Esmx 官方示例 Hub 的最终效果:一个页面里同时承载 Vue 2/3、React、Preact、Solid、Svelte、Lit 等 7 种框架、3 种打包工具构建的 15 个子应用,全部通过"一个 import map"统一管理,这正是模块链接三种角色协作的直观成果。

单个子应用(如 React 19 计数器)则以独立微应用的形式运行在统一平台中,互不干扰:

三种协作角色分别承担什么职责?

模块链接的协议事实全部写在package.json的一个esmx字段里,恰好四个可选子字段:

字段含义
entry框架入口(client / server),库模块可省略
exports带逻辑名的子路径映射,消费方永远看不到物理路径
provides本模块为消费方再导出的第三方包列表
uses你所消费的模块名列表,数组顺序有意义

三种角色覆盖所有工程场景,而且每份声明都只是"本地知识"——你可以在对其他模块一无所知的情况下写出来。

角色一:供给方(共享平台包)

供给方是提供共享能力的"基座",比如统一封装 UI、状态管理与公共依赖的shared包。它的exports暴露的是逻辑名而非物理路径,provides则声明了它愿意为下游再导出的第三方包(如vue@esmx/router):

{ "name": "shared", "version": "3.2.1", "esmx": { "exports": { "./ui": "./src/ui/index.ts", "./store": { "client": "./src/store.client.ts", "server": "./src/store.server.ts" } }, "provides": ["vue", "@esmx/router"] } }

消费方只需import 'shared/ui',即使供给方重命名了源文件,也不是破坏性变更。仓库中的 ssr-micro-shared/package.json 就是这样一个真实供给方示例。

角色二:消费方 + 供给方(功能远程)

大多数业务模块身兼两职:既消费共享平台的能力,又向更上层的宿主提供自己的业务导出。比如购物车模块cart,它usesshared,同时exports出自己的./widget

{ "name": "cart", "version": "1.8.0", "dependencies": { "shared": "^3.0.0" }, "peerDependencies": { "vue": "^3.4.0" }, "esmx": { "exports": { "./widget": "./src/cart-widget.ts" }, "uses": ["shared"] } }

注意这里没有手写的 imports 映射,也没有逐 specifier 的接线;版本范围就放在 npm 本来就放的地方——dependencies,并在构建时对照实际版本自动校验。

角色三:组合方(宿主)

宿主是聚合一切的最终应用,它只声明自己依赖了谁,其余交给模块链接的传递规则:

{ "name": "host", "version": "2.0.0", "dependencies": { "shared": "^3.0.0", "cart": "^1.5.0" }, "esmx": { "uses": ["shared", "cart"] } }

uses传递的:如果cartusesshared,那么 usescart的宿主会自动通过链条获得shared的供给。业务应用只声明一行,对链条深度毫不知情。参考真实宿主 ssr-micro-hub/package.json,它的uses列出了一长串子应用,却没有任何手写接线。

接线如何被推导?两条规则取代所有手写映射

模块链接的精髓在于"零接线",由两条规则完成:

合并规则supply(M) = merge(supply(uses[0]), …, supply(uses[n]), M.provides)——后面的条目覆盖前面的,模块自己的provides是隐含的最后一个元素。当两个模块供给同一个包时,uses数组的顺序决定谁赢(按从通用到具体排列,具体层胜出)。选举是逐 major 版本进行的,共存的 major(如 Vue 2 和 Vue 3)是互相隔离的孤岛,各有自己的赢家。

查找规则:打包器遍历你的代码时逐 specifier 判断——裸 specifier 出现在合并后的供给表里就外部化并接到赢家;哪里都找不到,则打包成自己的副本,由逐模块的 import-map scope 自动隔离。因此单实例共享是固有的,多版本共存也不需要额外词汇。

这套逻辑在源码中有清晰实现:module-link/config.ts 负责外部化与入口配置,module-link/manifest-plugin.ts 构建包含exportschunks的 manifest.json,入口统一在 module-link/index.ts。

用 esmx validate 免构建校验整张图

改完声明后,无需执行完整构建即可验证所有接线是否成立。esmx validate是整个解析过程的 dry run——覆盖挂载遍历、版本检查、供给合并、导出检查:

esmx validate # 人类可读报告 esmx validate --json # 机器可读信封,适合 CI / Agent

只有出现 error 级诊断才以非零码退出;仅有警告则退出 0。完整诊断分类(E_NOT_LINKEDE_VERSIONE_SCHEMAW_MULTI_MAJOR等)可查阅官方文档 module-linking.md 与核心实现 packages/core/src/module-config.ts。

实战:Vue 2 与 Vue 3 如何在同一平台共存?

多版本共存是模块链接最亮眼的场景。一个共享基座并排供给两个 major 的 Vue,每个业务应用只声明自己的版本范围,解析器自动把它们接到匹配的 major,全程没有任何手写 imports:

  • 共享基座sharedprovides: ["vue", "vue2", "@esmx/router"],其中vue2通过 npm 别名npm:vue@^2.7.0引入,每个 major 是独立的选举分组;
  • Vue 3 应用:声明peerDependencies: { "vue": "^3.5.0" }uses: ["shared"],只导出自己的路由配置;
  • Vue 2 应用:声明"vue": "npm:vue@^2.7.0",同样只写一行uses
  • 聚合宿主hostuses: ["shared", "vue2-app", "vue3-app"],每个子应用一行,组合子应用的单一路口。

构建好子应用后运行esmx validate --json,即可确认整张依赖图能解析。

模块链接 vs Module Federation:有何不同?

对比项Esmx 模块链接Module Federation
运行时原生 ESM + Import MapsWebpack/Rspack 运行时容器
开销零额外运行时Federation 运行时 + 共享作用域协商
SSR一等公民,SEO 友好需额外配置,历史上较脆弱
版本显式 provider,单一所有者运行时共享作用域协商

由于链接基于浏览器自身的模块系统,没有沙箱、没有私有加载器,同一份import在浏览器、SSR 与测试中都表现一致。

想亲自体验?

克隆仓库后即可在本地跑起包含 15 个子应用的完整示例:

git clone https://gitcode.com/gh_mirrors/genesis8/genesis

进入examples/micro-app目录,观察ssr-micro-shared(供给方)、各框架子应用(消费方 + 供给方)与ssr-micro-hub(组合方)三者之间如何用最少的声明完成最复杂的协作。理解了这三种角色,你就掌握了 Esmx 微前端架构的核心心智模型。

【免费下载链接】genesisNext-generation micro-frontend framework based on ESM, sandbox-free with zero runtime overhead, supporting multi-framework hybrid development项目地址: https://gitcode.com/gh_mirrors/genesis8/genesis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

← 返回列表