初次接触 Webpack 5 时,Earn Universe 赚取宇宙这个说法容易让人摸不着头脑。实际上,它是对 Webpack 5 核心新特性 Module Federation(模块联邦)的一种趣味化描述。模块联邦让多个独立构建的应用可以在运行时共享代码,就像把散落的星球连接成一个可以自由穿梭的宇宙,开发者因此能够赚取代码复用、独立部署和团队协作带来的红利。本文将以模块联邦为主线,结合 Webpack 5 的其他改进,详细讲解这一特性的原理、配置和实战收益。

一、什么是模块联邦:Webpack 5 的宇宙级能力
模块联邦是 Webpack 5 内置的一项核心特性,通过 ModuleFederationPlugin 插件来实现。它与传统的代码分割、外部依赖或 npm 包发布方式有本质区别:它允许一个应用在运行时从另一个独立构建的应用中加载模块,而不需要把这些模块预先打包进本地产物,也不需要发布到 npm 仓库。这意味着两个完全独立的团队可以各自构建、各自部署,然后在浏览器端动态地组合在一起。
为什么它会被戏称为 Earn Universe 赚取宇宙?因为模块联邦打破了项目之间的物理边界,让多个前端应用像星系一样连接成一个可扩展的宇宙。在这个宇宙中,每个应用既可以作为宿主(host)去消费其他应用的模块,也可以作为远程(remote)去暴露自己的组件。开发者可以按需引用远程模块,从而赚取跨项目复用的能力,并且通过共享依赖的单例控制避免 React、Vue 等核心库被重复加载,降低了产物体积和运行时冲突的可能性。
下面是一个典型的远程应用配置示例,它通过 exposes 字段暴露一个按钮组件,供其他应用在运行时加载。
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
二、核心概念:宿主、远程与共享依赖
在模块联邦的体系中,宿主(host)是发起加载动作的一方,远程(remote)是提供模块的一方。一个应用完全可以同时承担两种角色,例如它既暴露自己的组件,又消费其他应用的组件。配置时,exposes 字段用于声明对外暴露的模块路径,键名是其他应用引用时使用的名称;remotes 字段用于声明要消费的远程地址,地址通常指向远程应用构建产物中的入口文件,例如 remoteEntry.js。
shared 字段则是模块联邦实现依赖共享的关键。它允许开发者声明哪些依赖包需要共享,并可以进一步设置 singleton、requiredVersion 等选项。当 singleton 为 true 时,整个运行时中只允许存在一个该依赖的实例,即使宿主和远程各自安装了不同版本的 React,最终也只会加载一份,从而避免出现多个 React 副本导致的状态不一致和 Hook 报错问题。
模块的加载流程大致如下:宿主构建时不会打包远程模块,而是在代码中通过动态 import 语法请求远程模块;运行时,Webpack 会先加载远程入口文件,远程入口负责注册模块容器,随后返回模块工厂函数给宿主执行。下面是一个消费远程按钮组件的示例,其中使用了 lazy 和 <Suspense> 来优雅地处理加载中的状态。
import React, { lazy, Suspense } from 'react';
const RemoteButton = lazy(() => import('remoteApp/Button'));
function App() {
return (
<Suspense fallback={<div>加载中...</div>}>
<RemoteButton label="来自远程的按钮" />
</Suspense>
);
}
export default App;
三、实战收益:为什么说它能赚取宇宙
传统的微前端方案各有痛点:使用 iframe 虽然隔离性好,但通信复杂,样式和性能问题突出;通过 npm 包发布组件库需要统一版本和发版流程,更新周期较长;使用 monorepo 虽然能在源码层面共享代码,但构建过程仍然高度耦合,项目规模变大后构建时间会显著增加。模块联邦则提供了一种新的平衡:各团队保持独立构建和独立部署,同时在运行时按需组合,互不阻塞。
具体收益体现在多个方面。首先是减少重复依赖,宿主和远程共享 React 等核心库后,单个应用的产物体积明显下降。其次是更新远程模块后,宿主无需重新构建即可获取最新版本,发布节奏更加灵活。此外,它更适合多团队并行开发,每个团队维护自己的远程入口,通过约定的接口暴露组件,互不干扰。举例来说,一个电商平台可以让商品列表团队暴露 ProductList 组件,购物车团队负责消费该组件,双方独立开发、独立上线,集成成本极低。
当然,模块联邦也有需要注意的地方。共享依赖的版本需要团队之间提前协调,避免出现运行时兼容问题;远程入口文件是通过网络请求获取的,需要合理处理加载失败和超时状态;远程模块的接口变更要有版本管理机制,防止宿主因远程更新而出现异常。生产环境中建议将远程入口部署到 CDN,并配合合理的缓存策略来提升加载性能。
四、Webpack 5 其他新特性如何配合模块联邦
Webpack 5 不仅在模块联邦上做了重大升级,还带来了持久化缓存、资源模块和改进的 Tree Shaking 等特性,它们与模块联邦配合起来可以进一步提升开发体验和构建性能。持久化缓存能够把构建结果缓存到磁盘,二次构建时大幅提速,对于需要频繁集成远程模块的场景尤其有用,因为本地构建可以借助缓存快速完成,开发者能把更多时间花在业务逻辑上。
资源模块允许开发者直接导入图片、字体等静态资源,无需再额外配置 file-loader 或 url-loader,简化了配置复杂度。改进的 Tree Shaking 则通过更精确的副作用分析去除无用代码,降低产物体积,这在共享依赖和远程模块加载时显得尤为重要,因为更小的代码块意味着更快的网络传输和更低的运行时开销。
综合来看,Earn Universe 赚取宇宙并非官方术语,但它形象地描述了 Webpack 5 模块联邦带来的架构变化。掌握 ModuleFederationPlugin 的配置方法,理解宿主、远程与共享依赖的协作机制,就能够在实际项目中构建出更灵活、更高效的微前端架构,真正赚取这个宇宙带来的工程红利。