Module Federation webpack 5 - Separate Entry Points
Published: 2021-01-02 17:27:08

ui-components => Remote App
ui-consumer => Host App

**ui-components/webpack-config.js**

```
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const deps = require("./package.json").dependencies;

module.exports = (_, args) => ({
  output: {
    publicPath: "http://localhost:3000/",
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  devServer: {
    port: 3000,
  },
  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-react"],
          },
        },
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "ui",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        "./Cards": "./src/Cards",
        "./Header": "./src/Header",
      },
      shared: {
        ...deps,
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
});
```

**ui-consumer/webpack-config.js**

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

const deps = require("./package.json").dependencies;

module.exports = (_, args) => ({
  entry: {
    // ui: "ui",
    test1: {
      import: "./src/Test1/index.ts",
      filename: "[name].js",
      // dependOn: "ui",
    },
    poll: {
      import: "./src/Test2/index.ts",
      filename: "[name].js",
      // dependOn: "ui",
    },

    main: "./src/index.ts",
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  devServer: {
    port: 8081,
  },
  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "consumer",
      filename: "consumerEntry.js",
      remotes: {
        ui: "ui@http://localhost:3000/remoteEntry.js",
      },
      shared: {
        ...deps,
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
});
```

**src/index.html**
```
<body>
    <div id="app"></div>
    <div id="test1"></div> // to render Test1 
    <div id="test2"></div> // and Test2
  </body>
```


**Using separate entry points was giving me this error**

> container_entry:25 Uncaught (in promise) Error: Container initialization failed as it has already been initialized with a different share scope
while loading "./Header" from webpack/container/reference/ui
    at Object.init (container_entry:25)
    at initFn (poll.js:663)
    at async Promise.all (:8081/index 0)

**I was able to fix this error by doing two things**

1. Add **dependOn** property in entry points

```
 entry: {
    ui: "ui",
    test1: {
      import: "./src/Test1/index.ts",
      filename: "[name].js",
      dependOn: "ui",
    },
    test2: {
      import: "./src/Test2/index.ts",
      filename: "[name].js",
      dependOn: "ui",
    },
  },
``` 

2. Do not use remote modules in imported components of src/index.ts. I removed index.ts file from src folder.

Now components render fine but it gives me this error
> Uncaught TypeError: Cannot read property 'call' of undefined
    at __webpack_require__ (ui.js:468)
    at checkDeferredModulesImpl (ui.js:981)
    at Function.__webpack_require__.x (ui.js:999)
    at ui.js:1040
    at ui.js:1041