reactjswebpacklazy-loadingmicro-frontendwebpack-module-federation

Microfrontend component causes page to not load when using shared libraries


I am working on converting one of my projects to load components through a microfrontend via the ModuleFederationPlugin in webpack instead of an npm package.

I was able to get a proof of concept component working by rendering a very simple component in the MFE app in a different project. However, when I attempt to add in shared libraries the component no longer renders and the entire page is blank with no errors in the console or localhost terminal.

Here is the configuration when the process works:

Webpack for project sharing component

  new ModuleFederationPlugin({
    name: 'MFETest',
    filename: 'remoteEntry.js',
    exposes: {
      './MFETest': './MFETest/MFEComponent',
      }
   })

Basic test component

import React from 'react';

function MFETest() {
  return <div>Hello There</div>;
}

export default MFETest;

Webpack for project consuming component

new ModuleFederationPlugin({
   name: 'Host',
   remotes: {
       MFETest: `MFETest@http://localhost:444/remoteEntry.js`,
   },
})

Import of MFE in consuming component

const MFETest = React.lazy(() => import('MFETest/MFETest'));

This all works fine, but when I start to connect shared libraries that will be needed for the larger component I am working in the React.lazy import call fails and causes the entire page to be blank with no error messages.

Example of adding in shared libraries Webpack for project sharing component

new ModuleFederationPlugin({
        name: 'MFETest',
        filename: 'remoteEntry.js',
        exposes: {
          './MFETest': './MFETest/MFEComponent',
        },
        shared: {
          react: {
              singleton: true,
              requiredVersion: deps.react,
              eager: true,
          },
          'react-dom': {
              singleton: true,
              requiredVersion: deps['react-dom'],
              eager: true,
          },
        },
      })

Webpack for project consuming component

new ModuleFederationPlugin({
            name: 'Host',
            remotes: {
                MFETest: `MFETest@http://localhost:444/remoteEntry.js`,
            },
            shared: {
                react: {
                    singleton: true,
                    requiredVersion: deps.react,
                    eager: true,
                },
                'react-dom': {
                    singleton: true,
                    requiredVersion: deps['react-dom'],
                    eager: true,
                },
            },
        }),

Solution

  • The issue was I was setting the shared dependency as eager in both the projects which does not work correctly. I set eager to false for the project hosting the component and it worked properly:

    Webpack for project sharing the component

    new ModuleFederationPlugin({
            name: 'MFETest',
            filename: 'remoteEntry.js',
            exposes: {
              './MFETest': './MFETest/MFEComponent',
            },
            shared: {
              react: {
                  singleton: true,
                  requiredVersion: deps.react,
                  eager: false,
              },
              'react-dom': {
                  singleton: true,
                  requiredVersion: deps['react-dom'],
                  eager: false,
              },
            },
          })
    

    This made the project consuming the component work correctly but had the side effect that the project hosting it failed to load with an error that the shared module was not available for eager consumption. I was able to solve this issue by updating the index.tsx file to be in a bootstrap.tsx. This allowed webpack to load the shared dependencies before loading the main project. See this article for a full explanation https://www.linkedin.com/pulse/uncaught-error-shared-module-available-eager-rany-elhousieny-phd%E1%B4%AC%E1%B4%AE%E1%B4%B0/?source=post_page-----a547f77e7b54--------------------------------