使用Webpack Module Federation发布同一应用双版本遇加载问题
Webpack Module Federation 多版本远程加载异常解决
问题描述
我们使用Webpack Module Federation构建Web应用,用于功能实验性发布——需为部分用户加载同一应用的两个不同版本remoteEntry,但加载时出现脚本加载失败的异常。采用Promise动态远程加载方案,相关配置及报错信息如下:
主应用Webpack配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); const { ModuleFederationPlugin } = require('webpack').container; const ExternalTemplateRemotesPlugin = require('external-remotes-plugin'); const path = require('path'); const packageJsonDeps = require('./package.json').dependencies; module.exports = { entry: './src/index', mode: 'development', devServer: { static: path.join(__dirname, 'dist'), port: 3001, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['@babel/preset-react'], }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'app1', remotes: { app2: 'app2@[app2Url]/remoteEntry.js', app3: 'app3@[app3Url]/remoteEntry.js', }, shared: { react: { singleton: true, eager: true, requiredVersion: packageJsonDeps['react'], }, 'react-dom': { singleton: true, eager: true, requiredVersion: packageJsonDeps['react'], }, }, }), new ExternalTemplateRemotesPlugin(), new HtmlWebpackPlugin({ template: './public/index.html', }), ], };
提供方应用Webpack配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); const { ModuleFederationPlugin } = require('webpack').container; const path = require('path'); const packageJsonDeps = require('./package.json').dependencies; module.exports = { entry: './src/index', mode: 'development', devServer: { static: path.join(__dirname, 'dist'), port: 3003, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['@babel/preset-react'], }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'app2', filename: 'remoteEntry.js', exposes: { './App': './src/App', }, shared: { react: { singleton: true, eager: true, requiredVersion: packageJsonDeps['react'], }, 'react-dom': { singleton: true, eager: true, requiredVersion: packageJsonDeps['react'], }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], };
报错信息
Loading script failed.
(missing: http://localhost:3003/remoteEntry.js)
while loading "./App" from webpack/container/reference/app3
ScriptExternalLoadError: Loading script failed.
排查与解决步骤
1. 对齐远程应用命名与映射关系
主应用remotes中配置了app3: 'app3@[app3Url]/remoteEntry.js',但现有提供方应用的name为app2且仅部署在3003端口。针对双版本发布场景:
- 为第二个版本的提供方应用单独配置
name: 'app3',并部署到独立端口(如3004) - 确保
[app3Url]全局变量被正确赋值为第二个版本的部署地址(如http://localhost:3004)
2. 确保动态URL变量的正确注入
使用ExternalTemplateRemotesPlugin时,占位符对应的全局变量必须在主应用bundle加载前定义。在主应用的入口HTML中添加:
<script> // 对应app2的部署地址 window.app2Url = 'http://localhost:3003'; // 对应app3(第二个版本)的部署地址 window.app3Url = 'http://localhost:3004'; </script>
注意变量名必须与remotes配置中的占位符完全匹配(如[app3Url]对应window.app3Url)。
3. 验证远程资源的可访问性
- 直接在浏览器访问远程应用的
remoteEntry.js地址(如http://localhost:3003/remoteEntry.js、http://localhost:3004/remoteEntry.js),确认文件能正常返回 - 生产环境下需检查CORS配置,确保主应用域名有权限跨域请求远程资源
4. 确认共享依赖版本一致性
虽然报错为脚本加载失败,但共享依赖版本不匹配可能间接引发异常:
- 确保主应用与所有远程应用的
react、react-dom版本,与配置中requiredVersion指定的版本完全一致 - 确认
singleton: true配置生效,避免重复加载多版本依赖
内容的提问来源于stack exchange,提问作者Hari Soni
相关产品推荐
相关产品推荐

