Vite and Module Federation Makes Micro-Frontends EASY!

6 min read 5 months ago
Published on Aug 02, 2024 This response is partially generated with the help of AI. It may contain inaccuracies.

Table of Contents

Introduction

This tutorial will guide you through the process of setting up Module Federation with Vite and Rollup applications. You'll learn how to share components dynamically between two applications, set up a shared store for state management, and ensure compatibility with Webpack applications. By the end of this guide, you will understand the advantages of runtime code sharing in a micro-frontend architecture.

Chapter 1: Plugin Introduction

To start using Module Federation in your Vite application, you need to install the necessary plugin. Follow these steps:

  1. Install the Plugin

    • Access the documentation to understand the installation process and configuration options.
    • The plugin allows dynamic sharing of components across applications, enabling integration of different frameworks (e.g., React and Vue).
  2. Set Up Your Project

    • Create a new directory for your project, e.g., Vite Mod Fed.
    • Open your terminal and set up two applications:
      • Remote Application: This will share components.
      • Host Application: This will consume components.

Chapter 2: Remote Application Setup

Set up the remote application to expose a component:

  1. Create Remote Application

    • Run the command:
      pnpm create vite remote --template react
      
    • Navigate to the newly created directory.
  2. Install the Plugin

    • In the remote application, install the Module Federation plugin.
  3. Fix the Port Number

    • To ensure the URL remains consistent, modify the package scripts in package.json:
      "scripts": {
        "dev": "vite --port 5001"
      }
      
    • This ensures the application always runs on port 5001.
  4. Create a Button Component

    • Create a button component in src/Button.jsx:
      import React, { useState } from 'react';
      
      const Button = () => {
        const [count, setCount] = useState(0);
        return <button onClick={() => setCount(count + 1)}>Click me: {count}</button>;
      };
      
      export default Button;
      
  5. Import the Button in App

    • In src/App.jsx, import and use the button:
      import Button from './Button';
      
      function App() {
        return (
          <div>
            <h1>Remote Application</h1>
            <Button />
          </div>
        );
      }
      
      export default App;
      

Chapter 3: Host Application Setup

Now, create the host application that will consume the shared button component:

  1. Create Host Application

    • Run the command:
      pnpm create vite host --template react
      
    • Navigate to the host application directory.
  2. Install the Plugin

    • In the host application, install the Module Federation plugin.
  3. Configure the Host Application

    • Modify the configuration to reference the remote application:
      import { defineConfig } from 'vite';
      import federation from 'vite-plugin-federation';
      
      export default defineConfig({
        plugins: [
          federation({
            name: 'host',
            remotes: {
              remoteApp: 'http://localhost:5001/assets/remoteEntry.js',
            },
            shared: ['react', 'react-dom'],
          }),
        ],
      });
      
  4. Import the Remote Button

    • In src/App.jsx, import the button from the remote application:
      import Button from 'remoteApp/Button';
      
      function App() {
        return (
          <div>
            <h1>Host Application</h1>
            <Button />
          </div>
        );
      }
      
      export default App;
      

Chapter 4: Configuration Remote Module Federation

Configure the remote application to expose the button component:

  1. Modify Vite Configuration

    • Open vite.config.js in the remote application and set up the federation plugin:
      import { defineConfig } from 'vite';
      import federation from 'vite-plugin-federation';
      
      export default defineConfig({
        plugins: [
          federation({
            name: 'remoteApp',
            filename: 'remoteEntry.js',
            exposes: {
              './Button': './src/Button.jsx',
            },
            shared: ['react', 'react-dom'],
          }),
        ],
      });
      
  2. Build and Serve the Remote Application

    • Run the following commands:
      pnpm build
      pnpm serve
      
    • Ensure that remoteEntry.js is generated in the assets directory.

Chapter 5: Configuring Host Module Federation

Ensure the host application can consume the remote component:

  1. Access Host Configuration

    • Open the vite.config.js file in the host application.
    • Ensure it references the remote application correctly.
  2. Build and Preview the Host Application

    • Run:
      pnpm build
      pnpm preview
      
    • The host application should now display the shared button from the remote application.

Chapter 6: Implementing State Sharing

To share state between applications, utilize a state management library:

  1. Install Jotai

    • In both applications, install Jotai:
      pnpm install jotai
      
  2. Create Shared State in Remote

    • Create src/store.js in the remote application:
      import { atom } from 'jotai';
      
      export const countAtom = atom(0);
      
  3. Update Button Component to Use Shared State

    • Modify the button component to use the shared state:
      import { useAtom } from 'jotai';
      import { countAtom } from './store';
      
      const Button = () => {
        const [count, setCount] = useAtom(countAtom);
        return <button onClick={() => setCount(count + 1)}>Click me: {count}</button>;
      };
      
  4. Repeat for Host Application

    • In the host application, import the shared state and use it similarly.

Chapter 7: Webpack Interoperability

Test compatibility with a Webpack 5 application:

  1. Create a Webpack Host Application

    • Run the command:
      npx create-mf-app wp-host --port 8080 --template react
      
  2. Modify Webpack Configuration

    • Update the Webpack config to include the remote application:
      module.exports = {
        // other configurations
        plugins: [
          new ModuleFederationPlugin({
            name: 'wpHost',
            remotes: {
              remoteApp: 'remoteApp@http://localhost:5001/assets/remoteEntry.js',
            },
          }),
        ],
      };
      
  3. Import the Remote Button in Webpack Application

    • Use the shared button in the Webpack application.

Chapter 8: Monorepo Comparison

Explore the differences between build-time and runtime sharing:

  1. Set Up a Monorepo

    • Use Turborepo or a similar tool to create a monorepo structure.
    • In this structure, you can have shared components and stores that both applications reference.
  2. Analyze Pros and Cons

    • Build-time Sharing:
      • Pros: Coherent packages, easier TypeScript integration, reliable unit testing.
      • Cons: No runtime flexibility.
    • Runtime Sharing:
      • Pros: Seamless updates without redeploying.
      • Cons: Potential runtime issues, dependency on remote applications.

Conclusion

You have successfully set up Module Federation with Vite and Rollup applications. By following this guide, you learned how to share components dynamically, manage shared state, and ensure compatibility with existing Webpack applications. Consider the advantages and disadvantages of build-time versus runtime sharing to choose the best architecture for your projects. Start experimenting with micro-frontends and leverage the flexibility of Module Federation in your applications!