webpackcreate-react-appwebpack-dev-serverwebpack-module-federation

Webpack dev server stuck with CRA and module federation


I am running an application created with create-react-app 5.0.1 and wanted to introduce Webpack Module Federation, as I need to expose a part of it as a remote. I understand CRA doesn't support Module Federation yet, but supporting Webpack 5 it should be still possible to customize its config to achieve my goal.

So I used react-app-rewired to override CRA webpack config with the following lines

// config-overrides.js

const { ModuleFederationPlugin } = require('webpack').container
const deps = require('./package.json').dependencies

module.exports = function override(config) {
 config.plugins.push(
  new ModuleFederationPlugin({
    name: 'MyApp',
    shared: {
        react: {
            requiredVersion: deps.react,
            singleton: true,
        },
        'react-dom': {
            requiredVersion: deps['react-dom'],
            singleton: true,
        },
        'react-router-dom': {
            requiredVersion: deps['react-router-dom'],
            singleton: true,
        },
    },
    exposes: {
        './MyRemote': {
            import: './my/path/to/myfile.tsx',
            name: 'MyRemoteName',
        },
    },
  })
 )
}

While my npm run build works fine, if I run npm start my dev server (that is webpack-dev-server from CRA) hangs on Starting development server.... I left it hanging for half an hour before decide that there is an issue (:

Do you have any idea on what could be the root cause?

EDIT1: for testing purposes, I removed react-app-rewired, ejected, added ModuleFederationPlugin to webpack.config.js file and printed the webpack-dev-server config. Here is the output:

$ npm start

> telo-ui@10.0.0 start
> node scripts/start.js

>>> serverConfig {
  allowedHosts: 'all',
  headers: {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': '*',
    'Access-Control-Allow-Headers': '*'
  },
  compress: true,
  static: {
    directory: 'C:\\DEV\\Abstract\\telo-ui-4\\public',
    publicPath: [ '/' ],
    watch: {
      ignored: /^(?!C:\/DEV\/Abstract\/telo\x2dui\x2d4\/src\/).+\/node_modules\//g
    }
  },
  client: {
    webSocketURL: { hostname: undefined, pathname: undefined, port: undefined },
    overlay: { errors: true, warnings: false }
  },
  devMiddleware: { publicPath: '' },
  https: false,
  host: '0.0.0.0',
  historyApiFallback: { disableDotRule: true, index: '/' },
  proxy: undefined,
  onBeforeSetupMiddleware: [Function: onBeforeSetupMiddleware],
  onAfterSetupMiddleware: [Function: onAfterSetupMiddleware],
  port: 3000
}
(node:8652) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:8652) [DEP_WEBPACK_DEV_SERVER_ON_BEFORE_SETUP_MIDDLEWARE] DeprecationWarning: 'onBeforeSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
Starting the development server...

Solution

  • My Module Federation configuration was just wrong. Here is a good one that worked well for my remote container.

    new ModuleFederationPlugin({
            name: "myApp",
            exposes: {
                './mount': "./path/to/myApp.ts",
            },
            filename: "myApp.js",
            shared: {
                react: {
                    singleton: true,
                    requiredVersion: dependencies['react'],
                },
                'react-dom': {
                    singleton: true,
                    requiredVersion: dependencies['react-dom'],
                },
            },
        })