- The main Tech Stack
- Repository structure
- The main stitcher
- The mini stitchers
- The MFE repositories
- How a MFE is loaded
- Build
- Deployment
- Running on the production server
- UI library
- Testing
- Security
- Monitoring
- File structure in a repo
- State Management
One of the projects I am working on uses a proprietary micro frontend framework as the foundation, which is mainly based on Webpack Module Federation. In this post, I am going to decode the overall framework design.
The main Tech Stack
- Webpack Module Federation
- React
- Tailwind
Repository structure
1 | main-stitcher (MAIN STITCHER) |
Each of them is a Node.js project,which has package.json, webpackge.config.js and Dockerfile in the root folder.
The main stitcher
There are two business modules in it, most others are in the MFE repositories:
- Dashboard
- Login
There is also a register-config.json file which has mini stitcher information.
1 | { |
Note: The file content of the applicationConfigPath file is defined in the mini stitcher repository, which we will see in the next section.
The mini stitchers
There can be many mini stitchers in this structure. There are not many interesting things in a mini stitcher, it’s just a container for closely related sub applications.
There is a sourcelist.json and mini-stitcher-config.json file in a mini stitcher.
All sub apps are defined in the sourcelist.json file, it is used by pipeline to pull code from specific repositories and generate the deployable image.
1 | [ |
The mini-sitcher-config.json file has runtime configurations in the subapps.
1 | { |
The MFE repositories
They are in the lowest layer in the structure. In order to be loaded in the main stitcher, modules need to be exposed in webpack.config.js:
1 | new ModuleFederationPlugin({ |
We will get a URL for this sub app, something like:
1 | https://cdn.example.com/remote/remote-entry.js |
How a MFE is loaded
When a menu in the main stitcher clicked, the code in the Dashboard will try to get the MFE repository information. Then inject the remote script in the HTML document:
1 | const script = document.createElement('script'); |
Note: remote-entry.js does not contain the actual business logic, it is more like a factory.
1 | window["remoteApp"] = { |
To call the actual business code, we need to load the component:
1 | function loadComponent(scope: any, module: string) { |
Build
There is a build script in the main stitcher and a MFE repository, but not in a mini stitcher.
This job is done by a seperate pipeline repository microservice_microfrontend.git for mini stitchers. It will read the sourcelist.json file content in a mini stitcher during the deployment, and checkout all the repositores in it, run npm run build command seperately in each repository, finially copy all the generated files into a folder created for this mini stitcher.
Deployment
- We deploy the mini stitcher instead of individual MFE repos.
- Whenever we make changes in MFE, we will re-deploy the mini stitcher.
- The stitcher images are deployed by Jenkins pipelines using Helm to OpenShift.
Running on the production server
- A Pod is created for each stitcher deployment, which has Apache httpd server installed.
- The built static files during the Jenkins build stage are copied into an Apache image.
- When the Pod starts, Apache servers the static assets, include js files.
UI library
There is a custom UI library built with React for all the MFE repositories.
Testing
- Jest
- React Testing library
Security
- Black Duck
- Sonar Scan
Monitoring
- Elastic RUM (Real User Monitoring)
File structure in a repo
1 | |-- config |
File structure in the src folder
1 | |-- app |
State Management
The framework uses @ngneat/elf and @ngneat/elf-persist-state to store and manage the global state.