不能直接共享。模块联邦设计初衷是运行时动态加载UI组件,工具模块应通过shared配置实现版本对齐与单例复用,或采用Monorepo方案更可靠。

Webpack5 模块联邦能直接共享工具模块吗?
不能直接共享。模块联邦本质是运行时动态加载远程 exposes 的组件或模块,但工具函数(如 utils.js、apiClient.ts)通常不带 React/Vue 等框架上下文,也不符合“按需加载 UI 模块”的设计初衷。强行暴露会导致 Host 无法正确解析导出、类型丢失、Tree-shaking 失效等问题。
为什么用 shared 配置比 exposes 更适合工具模块
工具模块的核心诉求是“版本对齐 + 单例复用”,而非“跨项目渲染”。shared 正是为此设计:它让多个项目共用同一份已打包的依赖实例,避免重复打包和版本冲突。
- Host 和 Remote 都声明
shared: { '@company/utils': { singleton: true, requiredVersion: '^2.1.0' } },Webpack 会自动协商使用哪个版本,并确保只初始化一次 - 无需修改工具模块源码,保持原有
export function formatDate() {...}写法 - 构建产物中不会出现重复的
utils代码,体积更小 - 注意:必须保证所有项目都安装了兼容的
@company/utils版本,否则requiredVersion校验失败会报错Shared module is not available for eager consumption
如果非要通过 exposes 暴露工具模块,怎么避坑
仅限极简场景(如纯函数库、无副作用、无依赖),且必须绕过默认的模块解析限制:
- Remote 的
exposes必须写成'./utils': './src/utils/index.js',路径需精确到入口文件,不能是目录 - Host 中必须用
import('remoteApp/utils').then(m => m.default)动态导入,不能静态import,否则构建时报Cannot find module 'remoteApp/utils' - Remote 的
webpack.config.js要额外加library: { type: 'commonjs2' },否则导出对象结构被 Webpack 重写,Host 拿不到原始函数 - 类型提示会丢失,需手动维护
remoteApp.d.ts并在 Host 中/// <reference types="./types/remoteApp"></reference>
真正轻量又可靠的替代方案:Monorepo + TurboRepo
当工具模块变更频繁、多项目强耦合时,模块联邦反而增加复杂度。直接用 Monorepo 管理更自然:
- 把
@company/utils放进packages/utils,所有项目通过pnpm link或workspace:^引用 - 用
turbo run build --filter=host-app...remote-app实现增量构建,改一个工具模块,只重编依赖它的项目 - CI 中统一发布
@company/utils@next,各项目pnpm up @company/utils即可同步,比等远程模块热更新更可控 - 调试时直接跳转源码,不用在浏览器 Network 面板里扒
remoteEntry.js
模块联邦不是万能胶——它解决的是“运行时跨域模块加载”,而不是“如何复用工具代码”。选错技术路径,后期维护成本远高于初期省下的几行配置。

















