Module federation allows us to create micro frontends in a pretty simple way.
Start off by running
npx create-mf-app
You’ll be prompted for a few things (these may change in different versions of this app. so these are current settings)
- Pick the name of your app. This is essentially the name of the shell/host or main application (however you prefer to think of it). So I’m used to Shell application in MAUI, Xamarin Forms, WPF etc. So mine’s going to be named shell.
- Project Type. We’re going to choose Application (as this is our shell application)
- Port number. The default is 8080, but I’m going to choose 3000 (as I already have servers running on 8080 for other things).
- Framework. We’re going to be using react
- Language. I’m a TypeScript person, so I’m choosing typescript
- CSS Accept the default which is CSS
Now our shell will be created. So as the prompt will state
- cd shell
- npm install
- npm start
If all worked you’ll be presented by some large text stating the name of the app, framework etc.
Let’s now create another app in exactly the same way, obviously give it a different name (mine’s about), this is one of your micro frontends, also give it a different port, i.e. 8081 if you stuck with the default 8080 for the shell or in my case 3001.
Now go to that application and run it up using the commands below (again)
- cd about
- npm install
- npm start
If all went well we have an application (the shell) running and the about application running as well. So nothing too exciting to see here, but it just goes to show we’re developing “standard” React apps.
What we will now need to do, is create a component that we’re going to expose from this application. All I’m going to do is move the App.tsx code that shows the application name etc. into a component, so if you want to follow along, let’s add a components folder to the src folder and within that add a About.tsx file and moved the code from the App.tsx into it, so it looks like this
import React from "react"; export const About = () => ( <div className="container"> <div>Name: about</div> <div>Framework: react</div> <div>Language: TypeScript</div> <div>CSS: Empty CSS</div> </div> );
Now the App.tsx looks like this
import { About } from "./components/About"; const App = () => ( <About /> );
We need to make some changes to webpack.config.js, so locate the ModuleFederationPlugin section.
- Locate the exposes section and change it to look like this
exposes: { "./About": "./src/components/About" },
We expose all the components we want via this section and the shell app can then access them.
In your shell/container application we also need to amend the webpack.config.js and locate the remotes section, as you’ve probably worked out, this is going to register the micro frontends to be used within the shell/container. So mine looks like this
remotes: { about: "about@http://localhost:3001/remoteEntry.js" },
Let’s see if this work, open the shell/container’s App.tsx and add/change it to look like the below
import { About } from 'about/About'; const App = () => ( <div> <div className="container"> <div>Name: shell</div> <div>Framework: react</div> <div>Language: TypeScript</div> <div>CSS: Empty CSS</div> </div> <About /> </div> );
Run the about app and then the shell and if all went to plan you’ll see the “About” component in the shell.
A little more in depth ModuleFederationPlugin
This is really cool and we can see much of the work is done on the ModuleFederationPlugin, so let’s look a little more in depth into some of the key features
- name is the name we’re giving to our application
- library is used to determine how exposed code will be stored/retrieved
- filename by default is remoteEntry.js, but we can name it whatever we want, for example remoteAbout.js for our about app
- remotes, as we’ve seen these point to the “modules” we want to include and have the format
"app-name": "name@remote-host/entryFilename.js"
- exposes, as we’ve seen also the exposes is used to expose components etc. from our micro frontend, it has the format
"name" : "location-within-app"
- shared is used to share node libraries which the exposed module depends on.
Code
Checkout an example shell app with three Material UI/React micro frontend apps at microfrontend-react. Each app. uses Material UI and the shell app. brings them together to create the basics of an application with header, navigation bar and some content.
Obviously there’s a lot more to do to have a truly interactive micro frontend based application, but it’s a starting point.