Blog>
Snippets

React Microfrontends with Module Federation

Implement a microfrontend architecture using module federation to load a React component dynamically from another bundle at runtime.
// HostApp Webpack configuration
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'hostApp',
      remotes: {
        remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
      },
      shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
    }),
  ],
};
This is the webpack configuration for the host application where Module Federation is set up. 'remoteApp' is the name of the remote application, and 'http://localhost:3001/remoteEntry.js' is the location of the remote app's module federation entry point. Shared dependencies like React are marked as singleton to avoid loading multiple versions.
// RemoteApp Webpack configuration
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'remoteApp',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button',
      },
      shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
    }),
  ],
};
This is the webpack configuration for the remote application, which exposes the Button component so that it can be consumed by the host application. The 'filename' property sets the name of the build output file that the host will reference to load the remote code.
// Button component (RemoteApp)
import React from 'react';

const Button = () => (
  <button>Remote Button</button>
);

export default Button;
This is a React component defined in the remote application that will be dynamically loaded by the host application. It exports a simple button component.
// Host application
import React, { Suspense, lazy } from 'react';

const RemoteButton = lazy(() => import('remoteApp/Button'));

const App = () => (
  <div>
    <h1>Host Application</h1>
    <Suspense fallback={'Loading Button...'}>
      <RemoteButton />
    </Suspense>
  </div>
);

export default App;
This is the host application's main component. It uses React's lazy function and Suspense component to load the remote Button component from 'remoteApp'. When rendering, it will show a fallback text until the Button is loaded.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Host Application</title>
</head>
<body>
  <div id="app"></div>
  <script src="http://localhost:3000/main.js"></script>
  <script src="http://localhost:3001/remoteEntry.js"></script>
</body>
</html>
This is an HTML template for the host application. It includes script tags that load the host application's main bundle and the remote entry point from the remote application.
/* CSS for the button in RemoteApp */
button {
  background-color: #4CAF50;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
  border: none;
  border-radius: 4px;
}
This CSS snippet styles the button component in the remote application. It sets visual properties like background color, padding, font size, and border radius.