Search code examples
webpackmicro-frontendwebpack-module-federation

Webpack Module Federation error "TypeError: __webpack_modules__[moduleId] is not a function"


I try to implement a simple example about Module Federation with vanilla js functions.

Directory structure:

  ── packages
    ├── home
    │   ├── index.html
    │   ├── package.json
    │   ├── src
    │   │   └── index.js
    │   └── webpack.config.js
    └── nav
        ├── index.html
        ├── package.json
        ├── src
        │   ├── Header.js
        │   ├── index.js
        └── webpack.config.js

The expecting result is that home app render the Header of the nav.

Webpack config of nav

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

const deps = require("./package.json").dependencies;
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    optimization: {
        minimize: false
    },
    resolve: {
        extensions: [".js"],
    },
    output: {
        publicPath: "http://localhost:4001/",
    },
    plugins: [
        new ModuleFederationPlugin({
            name: "nav",
            filename: "remoteEntry.js",
            library: {type: 'var', name: 'nav'},
            exposes: {
                "./Header": "./src/Header"
            },
            shared: {
                ...deps
            }
        }),
        new HtmlWebpackPlugin({
            title: 'Module Federation Example',
        }),
    ],
}

Webpack config of home

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

const deps = require("./package.json").dependencies;
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    optimization: {
        minimize: false,
    },
    resolve: {
        extensions: [".js"],
    },
    output: {
        publicPath: "http://localhost:4000/",
    },
    plugins: [
        new ModuleFederationPlugin({
            name: "home",
            filename: "remoteEntry.js",
            remotes: {
                nav: "nav@http://localhost:4001/remoteEntry.js"
            },
            shared: {
                ...deps
            }
        }),
        new HtmlWebpackPlugin({
            title: 'Module Federation Example',
        }),
    ],
}

This is the Header:

export default () => {
    const node = document.createElement('div');
    node.innerHTML = 'Header';
    node.style = 'padding: 1em; box-sizing: border-box;display: flex;background: aquamarine;font-family:sans-serif;'
    return node;
}

In index.js file in home is where i import the Header:

import Header from 'nav/Header';

const Greetings = () => {
    const node = document.createElement('h1');
    node.innerHTML = 'App Shell';
    return node;
}

document.addEventListener("DOMContentLoaded", () => {
    document.body.appendChild(Greetings());
    document.body.appendChild(Header());
});

After build and serve on the url of the home app i retrieve this error:

Uncaught TypeError: __webpack_modules__[moduleId] is not a function
    at __webpack_require__ (main.js:66:41)
    at eval (index.js:2:68)
    at ./src/index.js (main.js:19:1)
    at __webpack_require__ (main.js:66:41)
    at main.js:217:37
    at main.js:219:12

You can reproduce here in StackBlitz.

I tried to add a library option library: {type: 'var', name: 'nav'}, in the ModuleFederationPlugin but i don't understand why is not working.

I expected to see the nav/Header rendered inside home app.


Solution

  • I found the solution.

    The error arises because I was importing the remote module directly into the index.js. The remote module is loaded asynchronously so it was not yet available for import and hence the error.

    The fastest solution is to import the remote modules into a bootstrap.js file to make sure they are available and import it in index.js

    index.js

        import("./bootstrap");
    

    bootstrap.js

        import Header from 'nav/Header';
        // other logics ...