React Micro Frontends with Vite

getjv

Jhonatan Morais

Posted on June 27, 2023

React Micro Frontends with Vite

I already have a number of SPA projects and a few projects using Next.js code, but I've always kept in my mind a curiosity on how micro-frontend works, and now its time to test.

As with backend micro-services, frontend micro-services are not a "silver bullet" architecture, so please use them only when really necessary.

In this post, I will show the project I used as PoC and how I set it up. Once the projects are turned on, we have only two steps: 1: Export components remotely and 2: Import them into the host.

Ignition - Inicial Projects

Let's save time... In my repo you can check out the 3 projects required for this tutorial. Download, install the npm dependencies, and go to step 1. If you wish get the final example use the brach related to the step two.

Step 1: Export a component from App-1

Now in the app-1 we will install the federation lib and export the component to be used by the app-container (host) follow the dots:

In your terminal go to app-1 folder and run:

   npm install @originjs/vite-plugin-federation --save-dev
Enter fullscreen mode Exit fullscreen mode

Now open the vite.config.js and add the federation config

   import { defineConfig } from 'vite'
   import react from '@vitejs/plugin-react'
   import federation from "@originjs/vite-plugin-federation";

   // https://vitejs.dev/config/
   export default defineConfig({
     plugins: [
         react(),
         federation({
           name: 'remote-app', // name of the fed group...
           filename: 'remoteEntry.js', // default file name
           // Modules to expose
           exposes: { 
             './Button': './src/components/Button.jsx',
           },
           shared: ['react','react-dom'] // libs/deps to be shared
         })
     ],
     build: {
       target: 'esnext' // needed to final build
     },
   })
Enter fullscreen mode Exit fullscreen mode

The important lines has comments to help you. but now we need to create the component we mapped. Create the componente: /src/components/Button.jsx'

   import React, {useEffect, useState} from "react";
   const Button = () => {
       const [count,setCount] = useState(0)
       return <button
           onClick={() => setCount(count +1)}
       > BTN APP 1: {count} </button>
   }
   export default Button
Enter fullscreen mode Exit fullscreen mode

Once the vite devServer do not generate physical files we need to build and preview our app-1 code. To do that open your package.json file and add this script:

   // others attributes
   "scripts": {
       // others cmds...
       "preview": "tsc && vite build && vite preview --port=5001 --strictPort"
   },
Enter fullscreen mode Exit fullscreen mode

Note the we added to preview command the && vite build to generate the files and && vite preview --port=5001 --strictPort to serve the files and force to be strict the port we need.

This port lock is super important because our host will save the remote uri address. Now just run npm run preview and once you access http://127.0.0.1:5001/assets/remoteEntry.js you should see some content... For the app-1 we are done.

Step 2 - Importing the Exported component into a host app.

The host config is super simple:

Go to app-container and install the federation lib too:

npm install @originjs/vite-plugin-federation --save-dev
Enter fullscreen mode Exit fullscreen mode

now add the federation plugin to your app-container/vite.config.ts and add the following:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import federation from "@originjs/vite-plugin-federation";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
      react(),
      federation({
        name: 'host-app',
        remotes: {
          remoteApp: // is the name set on remote but in camelCase "http://localhost:5001/assets/remoteEntry.js",
        },
        shared: ['react','react-dom'] 
      })
  ],
})

Enter fullscreen mode Exit fullscreen mode

Now just the remote component as a normal component. go to app-container/App.tsx and import the component as following:

import MyButton from 'remoteApp/Button
const App = () => {
   return <> <MyButton/> </>
}
export default App

Enter fullscreen mode Exit fullscreen mode

Take a note take about the component namings:

  • remoteApp is the name you map on vite federation plugin on host side and
  • Button is the mapped name of the component on remote project (app-1)

Now just run npm run dev and once app-container is on it will remote load the button from app-1 project.

Next steps

This is basically what is needed to work with federation and micro frontends. Here we just export/import a component but is possible to do the same with the state.

To integrate micro-frontend from different projects like Angular.js or Vue.js visit the examples in the library

You can checkout my project example to support your study or watch my video about this post, there I just execute the steps I described here.

I suggest you to check the video from Jack Herrington there he shows more examples about how to use federation and mono-repo.

Thats it. if this was useful to you please like and share.

See you!

💖 💪 🙅 🚩
getjv
Jhonatan Morais

Posted on June 27, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related