You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:47:12