在前端开发中,性能优化是一个永恒的话题。随着应用变得越来越复杂,开发者不断寻找新的方法来提高加载速度和用户体验。传统上,我们可能会使用Webpack的Externals功能来引入CDN资源,以减少打包体积和加快加载速度。然而,随着Webpack 5引入的模块联邦(Module Federation)功能,我们现在有了一个更强大的工具来优化我们的应用性能。
为什么不是Externals
Externals功能允许开发者从最终的bundle中排除某些依赖,这些依赖通常会被托管在CDN上,通过全局变量的形式在运行时提供。虽然这种方法可以减少应用的打包体积,但需要手动管理外部依赖,不适合复杂的模块共享需求。 兼容项目中引入了第三方资源库A,A又依赖了B,C,D 。Externals 并不能自动处理这些依赖关系。
使用模块联邦加载公共资源库
模块联邦是Webpack 5的一个新特性,它允许一个应用动态地从另一个应用加载代码,就像从本地模块导入一样。这为性能优化提供了新的可能性:
•动态加载:模块联邦支持动态加载远程模块,这意味着你可以根据需要懒加载模块,而不是在应用启动时加载所有模块。
•独立部署:每个远程模块可以独立部署和更新,不需要重新部署整个应用。
•共享模块:不同的应用可以共享模块,而不需要将其打包进每个应用的bundle中。
要使用模块联邦加载公共资源库,需要在资源库的Webpack配置中使用ModuleFederationPlugin来定义要暴露的模块:
// webpack.config.js
const {ModuleFederationPlugin} = require("webpack").container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'libraryName',
filename: 'remoteEntry.js',
exposes: {
'./Component': './src/Component',
},
// 其他配置...
}),
],
// 其他配置...
};
然后,在消费者应用的Webpack配置中,你需要添加一个远程模块的引用:
// webpack.config.js
const {ModuleFederationPlugin} = require("webpack").container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
remotes: {
libraryName: 'libraryName@https://cdn.example.com/remoteEntry.js',
},
// 其他配置...
}),
],
// 其他配置...
};
完整示例代码可以看这里: stackblitz.com/github/webp…
这种方法不仅减少了应用的初始加载时间,而且还提供了更好的缓存优势,因为公共库可以被多个应用共享,而不是被重复下载。需要注意的是,这种方式可能会引入不同版本的同一依赖。比如 项目中使用了 @ant-design/flowchart(依赖 @antv/x6) ,但是因为功能扩展的原因项目中又单独使用了@antv/x6 ,这种情况下,需要在host和remote应用的的package.json 中加上 @antv/x6 ,并确保和@ant-design/flowchart 中的主版本一致。实际的使用中,可以通过痛过Webpack插件的形式给出版本本地和远端公共库版本对比信息,并依据项目发布情况调整公共库APP的缓存时间。