Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/donadam2/micro-frontend-container-app
Example of creating app which is the host of another app using webpack module federation
https://github.com/donadam2/micro-frontend-container-app
react react-router-dom redux webpack-module-federation webpack5
Last synced: 17 days ago
JSON representation
Example of creating app which is the host of another app using webpack module federation
- Host: GitHub
- URL: https://github.com/donadam2/micro-frontend-container-app
- Owner: DonAdam2
- License: mit
- Created: 2021-04-29T08:14:15.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-07-09T13:50:05.000Z (6 months ago)
- Last Synced: 2024-07-10T16:34:30.364Z (6 months ago)
- Topics: react, react-router-dom, redux, webpack-module-federation, webpack5
- Language: JavaScript
- Homepage:
- Size: 4.15 MB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Table of Contents:
- [Overview](#micro-frontend-container)
- [Prerequisites](#prerequisites)
- [Installing & getting started](#installing--getting-started)
- [How to import a remote module and use it](#how-to-import-a-remote-module-and-use-it)
- [How to inject the remote module store slices into the current store](#how-to-inject-the-remote-module-store-slices-into-the-current-store)
- [Available scripts](#available-scripts)## Micro frontend container
- Uses ***module federation plugin*** from webpack to inject ***remote modules***.
- This app is the host of [Micro frontend inner app](https://github.com/DonAdam2/micro-frontend-inner-app)**_Note:_** This app uses live reloading for local development.
## Prerequisites
- nodeJS > 14.X.X or Docker
## Installing / Getting Started
### Development (locally):
- Clone repo => `git clone [email protected]:react-custom-projects/webpack-react-boilerplate.git`
- Navigate to project directory `cd webpack-react-boilerplate`
- Install dependencies => `yarn install`
- Start the development server => `yarn start`### Development (using Docker):
- Clone repo => `git clone [email protected]:react-custom-projects/webpack-react-boilerplate.git`
- Navigate to project directory `cd webpack-react-boilerplate`
- Install dependencies (required for prettier) => `yarn install`
- Start the development server => `docker-compose up web-dev`## Docker for production (_basic setup_) (modify it to your needs):
- Update the **_production_** section of the **_Dockerfile_** to meet your needs
- Run the following command to build your image => `docker-compose up web-prod`## How to import a _remote module_ and use it
- Open **webpack.common.js** file.
1- Import ***ModuleFederationPlugin***:```
const { ModuleFederationPlugin } = require('webpack').container
```2- Pass ***ModuleFederationPlugin*** to the ***plugins*** array:
```plugins: [
new ModuleFederationPlugin({
```3- Specify the name of the current app 678 in ***ModuleFederationPlugin***:
```new ModuleFederationPlugin({
name: 'app_container',
```4- Add the link of the ***remote module*** in `remotes object` of the ***ModuleFederationPlugin***, example:
```
new ModuleFederationPlugin({
remotes: {
inner_app: `inner_app@${isDevelopment ? remoteDevUrl : remoteProdUrl}/remoteEntry.js`,
},
```**_Notes:_**
- You must use the name of the ***remote module*** that you specified in the ***remote module*** webpack setup.
- You can add as many ***remote modules*** as you like by adding them to the `remotes object`
- **/buildTools/constants** contains ***remoteDevUrl*** and ***remoteProdUrl*** of the ***remote module***.5- Add the shared dependencies in ***ModuleFederationPlugin***:
```
new ModuleFederationPlugin({
shared: ['react', 'react-dom'],
}),
```6- Install **external-remotes-plugin** and add it below ***ModuleFederationPlugin*** in the plugins array:
```
//used to make sure that remote modules are loaded before the main bundle
new ExternalTemplateRemotesPlugin(),
```- Import the ***remote module*** lazily in the required place, example:
```
const RemoteApp = lazy(() => import('inner_app/App'));
```- Use it inside ErrorBoundary component:
```
{
//Reset the state of your app so the error doesn't happen again
console.log('Try again clicked');
}}
>
}
>
```## How to inject the _remote module_ store slices into the current store
- Install `redux-dynamic-middlewares` package if the **remote module** has middle wares.
- Open `/src/js/store/store.js` file:
1- Import `dynamicMiddlewares` from `redux-dynamic-middlewares` package:
```
import dynamicMiddlewares from 'redux-dynamic-middlewares'
```
2- Import `configureStore`:```
import { configureStore } from '@reduxjs/toolkit';
```
3- Import your redux slices:
```
import { reducerSlices } from './reducerSlices';
```
4- Create your redux store and pass to it **dynamicMiddlewares**:
```
export default configureStore({
reducer: reducerSlices,
devTools: isDevelopment,
middleware: (getDefaultMiddleware) => {
if (isDevelopment) {
const { logger } = require('redux-logger'),
middlewares = [logger, dynamicMiddlewares];return getDefaultMiddleware().concat(middlewares);
}return getDefaultMiddleware();
},
});
```5- Add **createReducer** function:
```
//used to merge dynamic reducer slices into static reducer slices
export const createReducer = (asyncReducers) =>
combineReducers({
...reducerSlices,
...asyncReducers,
});
```
- Open the component in which you want to use the imported module:
1- Import `addMiddleware` from `redux-dynamic-middlewares` package:```
import { addMiddleware } from 'redux-dynamic-middlewares';
```
2- Import current app **store** and **createReducer** function:```
import store, { createReducer } from '@/js/store/store';
```
3- Import the `remote module` lazily:```
const RemoteApp = lazy(() => import('inner_app/App'));
```
2- Create **injectMiddleWares** function in the component:```
const injectMiddleWares = (middleWares) => {
middleWares.forEach((el) => addMiddleware(el));
};
```3- Create **injectSlices** function in the component:
```
const injectSlices = (asyncReducerSlices) => {
let asyncReducers = {};
Object.entries(asyncReducerSlices).forEach((el) => (asyncReducers[el[0]] = el[1]));store.replaceReducer(createReducer(asyncReducers));
};
```
4- Pass `store`, `injectSlices` and `injectMiddleWares` to the `remote module`:```
```## Available Scripts
In the project directory, you can run:
### `yarn start`
Runs the app in the development mode.
It will open [http://localhost:3000](http://localhost:3000) automatically in the browser to see your app.All changes will be injected automatically without reloading the page.
You will see in the console the following:
- All redux store related changes
- Any of the following errors:
1. Linting errors.
2. Code format errors (because of [prettier](https://prettier.io/))### `yarn build`
Builds the app for production to the `dist` folder.
It correctly bundles React in production mode and optimizes the build for the best performance.The build is minified and the filenames include the hashes.
Your app is ready to be deployed!### `yarn build:serve`
Serves the app on [http://localhost:8080](http://localhost:8080) from the `dist` folder to check the production version.
**_Note:_** Use this script only if you ran the build script `yarn build`.
### `yarn analyze-bundle`
It allows you to analyze the bundle size.