Vite and Module Federation Makes Micro-Frontends EASY!
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:
-
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).
-
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.
- Create a new directory for your project, e.g.,
Chapter 2: Remote Application Setup
Set up the remote application to expose a component:
-
Create Remote Application
- Run the command:
pnpm create vite remote --template react
- Navigate to the newly created directory.
- Run the command:
-
Install the Plugin
- In the remote application, install the Module Federation plugin.
-
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.
- To ensure the URL remains consistent, modify the package scripts in
-
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;
- Create a button component in
-
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;
- In
Chapter 3: Host Application Setup
Now, create the host application that will consume the shared button component:
-
Create Host Application
- Run the command:
pnpm create vite host --template react
- Navigate to the host application directory.
- Run the command:
-
Install the Plugin
- In the host application, install the Module Federation plugin.
-
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'], }), ], });
- Modify the configuration to reference the remote application:
-
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;
- In
Chapter 4: Configuration Remote Module Federation
Configure the remote application to expose the button component:
-
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'], }), ], });
- Open
-
Build and Serve the Remote Application
- Run the following commands:
pnpm build pnpm serve
- Ensure that
remoteEntry.js
is generated in theassets
directory.
- Run the following commands:
Chapter 5: Configuring Host Module Federation
Ensure the host application can consume the remote component:
-
Access Host Configuration
- Open the
vite.config.js
file in the host application. - Ensure it references the remote application correctly.
- Open the
-
Build and Preview the Host Application
- Run:
pnpm build pnpm preview
- The host application should now display the shared button from the remote application.
- Run:
Chapter 6: Implementing State Sharing
To share state between applications, utilize a state management library:
-
Install Jotai
- In both applications, install Jotai:
pnpm install jotai
- In both applications, install Jotai:
-
Create Shared State in Remote
- Create
src/store.js
in the remote application:import { atom } from 'jotai'; export const countAtom = atom(0);
- Create
-
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>; };
- Modify the button component to use the shared state:
-
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:
-
Create a Webpack Host Application
- Run the command:
npx create-mf-app wp-host --port 8080 --template react
- Run the command:
-
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', }, }), ], };
- Update the Webpack config to include the remote application:
-
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:
-
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.
-
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.
- Build-time Sharing:
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!