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

Webpack 5 Module Federation报错:容器中模块不存在,求排查方案

问题描述

我尝试用Single SPA结合Webpack 5的Module Federation构建远程/宿主模式的微前端(MFE),但宿主应用抛出“Module doesn't exists in the container”错误。以下是相关配置代码:

远程应用Webpack配置

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const deps = require("./package.json").dependencies;
module.exports = {
  output: {
    publicPath: "http://localhost:3001/",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3001,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.(png|jpg|jpeg|svg)$/,
        exclude: /node_modules/,
        use: {
          loader: "file-loader",
        },
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "mfe",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        "/EventListing":"./src/Events/EventListing",
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
};

宿主应用Webpack配置

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

const deps = require("./package.json").dependencies;
module.exports = {
  output: {
    publicPath: "http://localhost:3000/",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3000,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "host",
      filename: "remoteEntry.js",
      remotes: {
        "mfe":"mfe@http://localhost:3001/remoteEntry.js"
      },
      exposes: {},
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
};

宿主应用index.tsx代码

import { registerApplication, start } from 'single-spa';
import './index.d';
registerApplication(
  'event-listing',
  () => import('mfe/EventListing'),
  location => location.pathname.startsWith('/')
);

start();

宿主应用HTML代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>host</title>
</head>

<body>
  <div id="single-spa-application:event-listing"></div>
</body>

</html>

问题修复方案

1. 修正暴露模块的路径格式

远程应用exposes配置中,暴露路径开头的斜杠会导致宿主引用路径不匹配。修改远程Webpack配置的exposes:

exposes: {
  "./EventListing": "./src/Events/EventListing",
},

2. 确保远程模块符合Single SPA生命周期规范

Single SPA要求微前端必须导出bootstrap、mount、unmount三个生命周期函数,检查EventListing文件是否正确实现:

import React from 'react';
import ReactDOM from 'react-dom/client';
import EventListingComponent from './EventListingComponent';

export const bootstrap = async () => {
  // 初始化逻辑,如预加载资源
};

export const mount = async (props: any) => {
  const root = ReactDOM.createRoot(
    document.getElementById(props.domElementId) as HTMLElement
  );
  root.render(<EventListingComponent />);
};

export const unmount = async (props: any) => {
  const root = ReactDOM.createRoot(
    document.getElementById(props.domElementId) as HTMLElement
  );
  root.unmount();
};

3. 确保远程Entry文件加载完成

可在宿主HTML中手动引入远程Entry,避免加载时序问题:

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>host</title>
  <script src="http://localhost:3001/remoteEntry.js"></script>
</head>

或用Single SPA的loadScript动态加载:

import { registerApplication, start, loadScript } from 'single-spa';

registerApplication(
  'event-listing',
  async () => {
    await loadScript('http://localhost:3001/remoteEntry.js');
    return import('mfe/EventListing');
  },
  location => location.pathname.startsWith('/')
);

start();

4. 验证远程模块路径正确性

确认./src/Events/EventListing路径指向的文件存在,且是导出生命周期函数的入口文件(而非单纯组件)。若文件结构为src/Events/EventListing/index.tsx,需调整路径为./src/Events/EventListing/index,或确保Webpack能自动解析目录入口。

5. 对齐共享依赖版本

检查宿主与远程应用的react、react-dom版本是否一致,确保Webpackshared配置中的requiredVersion与package.json中的依赖版本匹配,避免版本冲突导致加载失败。


内容的提问来源于stack exchange,提问作者Peter Wilson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:45:38