Siddhartha Chowdhury
Siddhartha Chowdhury

Reputation: 2732

Webpack ModuleFederationPlugin and HMR "Cannot set properties of undefined"

Brief

Hello community!

I have been trying Webpack ModuleFederationPlugin with react and typescript in my current POC. So I have 2 applications ChildApp that exposes a module and a HostApp that consumes the exposed module.

So far I am getting the exposed module into my host application. However when I try to make changes in the host react component the HMR fails and emits error:

Error on change in host component

What I have tried

I found sources with same issue in Github here and tried to apply the suggested solution but no success. I have tried both in HostApp and ChildApp to play around with chunks like this

// name of child federation config is: "editor"
new HtmlWebpackPlugin({
  excludeChunks: ['editor'],
   or
  chunks: ['main']
}),

Code reference:

Because the application has many files, instead of polluting here with snippets I am sharing the POC repo below, still the two webpack configurations here for quick look

webpack.config.js in Child app

module.exports = {
    mode: "development",
    entry: "./src/index.ts",
    output: {
        filename: "[name].[contenthash].bundle.js",
        path: path.resolve(__dirname, "dist"),
    },
    module: {
        rules: [
            {
                test: /\.(ts|tsx)$/,
                exclude: /node_modules/,
                use: "babel-loader",
            },
        ],
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"],
    },
    devServer: {
        port: 8081,
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html",
            chunks: ["main"],
        }),
        new ModuleFederationPlugin({
            name: "editor",
            filename: "remoteEntry.js",
            exposes: {
                "./Editor": "./src/exposed.ts",
            },
            shared: {
                ...deps,
                react: {
                    eager: true,
                    singleton: true,
                    requiredVersion: deps.react,
                },
                "react-dom": {
                    eager: true,
                    singleton: true,
                    requiredVersion: deps["react-dom"],
                },
            },
        }),
    ],
};

webpack.config.js in Hostapp

    module.exports = {
    mode: "development",
    entry: "./src/index.ts",
    output: {
        clean: true,
        filename: "[name].[contenthash].bundle.js",
        path: path.resolve(__dirname, "dist"),
    },
    module: {
        rules: [
            {
                test: /\.(ts|tsx)$/,
                exclude: /node_modules/,
                use: "babel-loader",
            },
        ],
    },
    devServer: {
        port: 8080,
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html",
        }),
        new ModuleFederationPlugin({
            remotes: {
                editorMFE: "editor@http://localhost:8081/remoteEntry.js",
            },
            shared: {
                ...deps,
                react: {
                    eager: true,
                    singleton: true,
                    requiredVersion: deps.react,
                },
                "react-dom": {
                    eager: true,
                    singleton: true,
                    requiredVersion: deps["react-dom"],
                },
            },
        }),
    ],
};

Resof the code can be found in github link below

  1. Github (recommended)
  2. Codesandbox (just for code, there are different errors here)

I am so close to finishing this POC just this HMR issue is one big blocker in the way.

Please help. Thanks in adavnce 🙏

Upvotes: 0

Views: 1080

Answers (1)

sleepwalker
sleepwalker

Reputation: 1032

The issue is caused by content hashing used in output section of webpack.config.

You'll need HMR for dev purposes only. So feel free to update your config for dev env - to not use specific output settings.

  1. At your host webpack config set:
   output: {
       uniqueName: "host"
   }
  1. At your editor mfe webpack config set:
    output: {
        uniqueName: "editor",
        publicPath: "http://localhost:8081/",
    }

Also make sure that you have CORS set for dev-server, cause ports differ. You need it for editor mfe only.

    devServer: {
        port: 8081,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
            "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
          }
    },

p.s. As I cannot put the external links here - there is a series of module federation articles from "angular architects", so you'll find many useful things there as well.

Upvotes: 0

Related Questions