Leveraging Module Federation with Single-spa for Micro Frontends

Leveraging Module Federation with Single-spa for Micro Frontends

Leveraging Module Federation with Single-spa for Micro Frontends

Micro frontends have gained popularity in recent years as a solution to the challenges of building and maintaining large-scale web applications. They allow developers to break down monolithic applications into smaller, more manageable pieces. Module Federation, a feature introduced in Webpack 5, simplifies code sharing between JavaScript applications and is a perfect fit for micro frontend architectures. In this article, we'll explore how to leverage Module Federation with Single-spa, a JavaScript framework for building micro frontends.

What is Single-spa?

Single-spa is a JavaScript framework that enables you to build, deploy, and maintain micro frontend architectures. It allows you to develop and deploy your applications in a decoupled manner, making it easier to scale and maintain your codebase. With Single-spa, you can create applications using different frameworks and technologies, such as React, Angular, or Vue, and have them work seamlessly together.

Why use Module Federation with Single-spa?

Module Federation simplifies code sharing between JavaScript applications, making it a great fit for micro frontend architectures. Combining Module Federation with Single-spa allows you to:

  1. Share dependencies between micro frontends, reducing the overall bundle size.
  2. Load micro frontends lazily, improving the initial load time.
  3. Enable independent deployments, allowing each team to work autonomously.
  4. Improve development workflows by isolating each micro frontend's codebase.

Getting Started

In this tutorial, we will demonstrate how to build a simple micro frontend architecture using Module Federation and Single-spa. We will create two applications, `app1` and `app2`, using React as the frontend framework.

Prerequisites

Before starting, make sure you have the following installed on your machine:

  • Node.js (v12 or higher)
  • NPM or Yarn

Setting up the project

1. Create two new React applications using create-react-app:

  1. npx create-react-app app1
  2. npx create-react-app app2

2. Navigate to each application's root directory and install the required dependencies:

  1. cd app1
  2. npm install --save single-spa single-spa-react
  3.  
  4. cd ../app2
  5. npm install --save single-spa single-spa-react

3. Install webpack and webpack-cli as devDependencies in both applications:

  1. npm install --save-dev webpack@5 webpack-cli@4

4. Install `html-webpack-plugin` and `webpack-dev-server` as devDependencies in both applications:

  1. npm install --save-dev html-webpack-plugin webpack-dev-server

Configuring Webpack and Module Federation

1. Create a `webpack.config.js` file in the root directory of each application and configure the basic Webpack settings:

  1. const HtmlWebpackPlugin = require('html-webpack-plugin');
  2.  
  3. module.exports = {
  4. entry: './src/index.js',
  5. output: {
  6. publicPath: 'auto',
  7. },
  8. module: {
  9. rules: [
  10. {
  11. test: /\.jsx?$/,
  12. exclude: /node_modules/,
  13. use: {
  14. loader: 'babel-loader',
  15. options: {
  16. presets: ['@babel/preset-react'],
  17. },
  18. },
  19. },
  20. ],
  21. },
  22. plugins: [
  23. new HtmlWebpackPlugin({
  24. template: './public/index.html',
  25. }),
  26. ],
  27. };

2. In the same `webpack.config.js` file, add the Module Federation plugin configuration for both applications:

  1. const HtmlWebpackPlugin = require('html-webpack-plugin');
  2. const { ModuleFederationPlugin } = require('webpack').container;
  3.  
  4. module.exports = {
  5. // ...
  6. plugins: [
  7. new ModuleFederationPlugin({
  8. name: 'app1', // Set this to 'app2' for the app2 configuration
  9. exposes: {
  10. './App': './src/App',
  11. },
  12. }),
  13. new HtmlWebpackPlugin({
  14. template: './public/index.html',
  15. }),
  16. ],
  17. };

This configuration exposes the `App` component from each application so that it can be consumed by other applications.

3. Update the scripts section in each application's `package.json` file to use the custom Webpack configuration:

  1. "scripts": {
  2. "start": "webpack serve --mode development",
  3. "build": "webpack --mode production"
  4. }

Configuring Single-spa

1. In each application's `src` directory, create a new file named `single-spa-config.js` with the following content:

  1. import * as singleSpa from 'single-spa';
  2. import * as singleSpaReact from 'single-spa-react';
  3.  
  4. async function loadApp1() {
  5. const app = await import('app1/App');
  6. return singleSpaReact.default({
  7. React,
  8. ReactDOM,
  9. rootComponent: app.default,
  10. });
  11. }
  12.  
  13. async function loadApp2() {
  14. const app = await import('app2/App');
  15. return singleSpaReact.default({
  16. React,
  17. ReactDOM,
  18. rootComponent: app.default,
  19. });
  20. }
  21.  
  22. singleSpa.registerApplication({
  23. name: 'app1',
  24. app: loadApp1,
  25. activeWhen: '/app1',
  26. });
  27.  
  28. singleSpa.registerApplication({
  29. name: 'app2',
  30. app: loadApp2,
  31. activeWhen: '/app2',
  32. });
  33.  
  34. singleSpa.start();

This configuration imports the `App` components exposed by the Module Federation plugin and registers them with Single-spa.
2. Update the `index.js` file in each application to use the `single-spa-config.js` file:

  1. import './single-spa-config';

Running the applications

  1. Start both applications by running `npm start` in their respective root directories.
  2. Open your browser and navigate to http://localhost:8080/app1 and http://localhost:8081/app2 to see the applications running.
  3. You can now switch between the applications using the `/app1` and `/app2` routes.

Conclusion

In this article, we have demonstrated how to use Module Federation and Single-spa to create a micro frontend architecture. By combining these technologies, you can build scalable and maintainable web applications that take advantage of the latest advancements in frontend development.

We use cookies to improve your browsing experience. By continuing to use this website, you consent to our use of cookies. Learn More