React Micro Frontends with Vite
Tags: react, vite, microservices, webdev
Published: 2023-06-27 21:01:40

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](https://github.com/getJv/getjv-micro-fe-react) 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: 

   ```bash
   npm install @originjs/vite-plugin-federation --save-dev
   ```

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

   ```javascript
   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
     },
   })
   ```

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'`

   ```javascript
   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
   ``` 

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:

   ```javascript
   // others attributes
   "scripts": {
       // others cmds...
       "preview": "tsc && vite build && vite preview --port=5001 --strictPort"
   },
   ```
 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: 
```bash
npm install @originjs/vite-plugin-federation --save-dev
``` 

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

```javascript
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'] 
      })
  ],
})

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

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

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](https://github.com/originjs/vite-plugin-federation#example-projects)

You can [checkout my project example](https://github.com/getJv/getjv-micro-fe-react/tree/step2-add-federation) to support your study or [watch my video about this post](https://youtu.be/ymaPetOe6Zg), there I just execute the steps I described here.

I suggest you to [check the video from Jack Herrington](https://www.youtube.com/watch?v=t-nchkL9yIg&ab_channel=JackHerrington) 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!