Aphiwad Chhoeun

Module Federation

Share code across multiple applications using a federated architecture

Module Federation is a powerful feature introduced in Webpack 5 that allows developers to share code across multiple applications. It enables different applications to share modules or even entire applications without the need for a common build step or deployment process. This allows for greater modularity and flexibility in application development.

In this blog post, we will discuss the concept of Module Federation and provide a few examples of how it can be used.

What is Module Federation?

Module Federation is a way to share code across multiple applications using a federated architecture. It allows developers to create a shared module or application, which can then be used by other applications that require it.

With Module Federation, each application has its own separate build process, but they can share modules at runtime. This makes it possible to build micro-frontends, where different parts of the UI are built by different teams and brought together at runtime.

Module Federation is not a new concept, and it has been used in different ways in the past. However, with the introduction of Webpack 5, it has become much easier to implement.

Example

Let’s say we have two applications, App1 and App2, and we want to share a React component between them. We can create a separate module for the component and use Module Federation to share it between the two applications.

In the first step, we create a new React component module:

// shared-components.js
import React from 'react'

export function SharedButton(props) {
  return <button className="shared-button">{props.children}</button>
}

Next, we configure the Webpack config for both applications to use Module Federation:

// webpack.config.js for App1
const { ModuleFederationPlugin } = require('webpack').container

module.exports = {
  // ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'app1',
      filename: 'remoteEntry.js',
      exposes: {
        './SharedButton': './src/shared-components.js',
      },
    }),
  ],
}
// webpack.config.js for App1
const { ModuleFederationPlugin } = require('webpack').container

module.exports = {
  // ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'app1',
      filename: 'remoteEntry.js',
      exposes: {
        './SharedButton': './src/shared-components.js',
      },
    }),
  ],
}

In the above example, we configure App1 to expose the SharedButton component as ./SharedButton, and App2 to consume it from the remote app1 entry point. When App2 is built, it will automatically download and load the SharedButton component from App1.

Now we can use the shared component in both applications:

// App1
import { SharedButton } from './src/shared-components'

function App() {
  return (
    <div className="App">
      <SharedButton>Hello from App1</SharedButton>
    </div>
  )
}
// App2

import React from 'react'
const { SharedButton } = React.lazy(() => import('app2/Button'))

function App() {
  return (
    <div className="App">
      <React.Suspense fallback="Loading Button">
        <SharedButton>Hello from App2</SharedButton>`
      </React.Suspense>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

I hope this has given you a good introduction of how Module Federation works and how it can be used in your own projects.