Implementing Micro Frontends with Next.js and Module Federation

0

Implementing Micro Frontends with Next.js and Module Federation

In today’s web development landscape, complexity and scale have become significant challenges. Attempting to implement all features within a single application often leads to difficulties in management and maintenance. The solution to this problem is micro frontends. Micro frontends break down each function into independent applications, which are then integrated and managed as a whole. In this article, we will explore how to implement micro frontends using Next.js and Module Federation.

What is Module Federation?

Module Federation is a feature introduced in Webpack 5 that allows different applications to share and load modules from each other. This enables the development and deployment of large-scale applications as multiple independent micro frontends. Each micro frontend maintains its own bundle while dynamically loading necessary modules.

Combining Next.js with Module Federation

Next.js is a React-based framework that supports server-side rendering (SSR) and static site generation (SSG). Combining Next.js with Module Federation allows for the management of multiple micro frontends within Next.js applications. This is facilitated by the NextFederationPlugin.

Setting Up NextFederationPlugin

First, install NextFederationPlugin.

npm install @module-federation/nextjs-mf

Next, modify the `next.config.js` file to configure the plugin.

const NextFederationPlugin = require('@module-federation/nextjs-mf');

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.plugins.push(
        new NextFederationPlugin({
          name: 'container', // Host application name
          filename: 'static/chunks/remoteEntry.js',
          remotes: {
            flight: 'flight@http://localhost:3001/_next/static/remoteEntry.js',
            hotel: 'hotel@http://localhost:3002/_next/static/remoteEntry.js',
          },
          exposes: {
            './NavBar': './components/NavBar', // Exposed module
          },
          shared: {
            react: {
              singleton: true,
              eager: true,
              requiredVersion: false,
            },
            'react-dom': {
              singleton: true,
              eager: true,
              requiredVersion: false,
            },
          },
        })
      );
    }

    return config;
  },
};

In this configuration, `name` specifies the host application’s name, `remotes` defines the entry points of external applications (micro frontends), `exposes` lists the modules to be exposed by the host application, and `shared` specifies the common libraries to be used.

Configuring Remote Applications

Each remote application also needs configuration. For example, the `next.config.js` file of the `flight` application can be set up as follows:

const NextFederationPlugin = require('@module-federation/nextjs-mf');

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.plugins.push(
        new NextFederationPlugin({
          name: 'flight', // Remote application name
          filename: 'static/remoteEntry.js',
          exposes: {
            './FlightDetails': './components/FlightDetails', // Exposed module
          },
          shared: {
            react: {
              singleton: true,
              eager: true,
              requiredVersion: false,
            },
            'react-dom': {
              singleton: true,
              eager: true,
              requiredVersion: false,
            },
          },
        })
      );
    }

    return config;
  },
};

Using Modules

The host application can use remote modules as follows:

import dynamic from 'next/dynamic';

const FlightDetails = dynamic(() => import('flight/FlightDetails'), { ssr: false });

export default function HomePage() {
  return (
    <div>
      <h1>Home Page</h1>
      <FlightDetails />
    </div>
  );
}

In this example, `dynamic` is used to dynamically load the `FlightDetails` module from the `flight` application. This approach utilizes Next.js’s dynamic import to delay module loading during server-side rendering.

Conclusion

By using Next.js and Module Federation, you can manage large-scale applications as multiple micro frontends efficiently. Each micro frontend can be developed and deployed independently, with necessary modules dynamically loaded. This architecture enhances development speed, reduces team dependencies, and simplifies maintenance.

NextFederationPlugin makes it easy to implement Module Federation in Next.js applications, helping to manage the complexities of modern web development effectively. Try implementing micro frontends with Next.js and Module Federation to create more flexible and scalable applications.

Leave a Reply