{"id":22994371,"url":"https://github.com/donadam2/micro-frontend-container-app","last_synced_at":"2025-08-13T22:31:41.602Z","repository":{"id":125808269,"uuid":"362740997","full_name":"DonAdam2/micro-frontend-container-app","owner":"DonAdam2","description":"Example of creating app which is the host of another app using webpack module federation","archived":false,"fork":false,"pushed_at":"2024-07-09T13:50:05.000Z","size":4351,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-07-10T16:34:30.364Z","etag":null,"topics":["react","react-router-dom","redux","webpack-module-federation","webpack5"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DonAdam2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-04-29T08:14:15.000Z","updated_at":"2024-07-09T13:50:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"d3e768cc-3b38-4c27-bb1d-778fd0f02a15","html_url":"https://github.com/DonAdam2/micro-frontend-container-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DonAdam2%2Fmicro-frontend-container-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DonAdam2%2Fmicro-frontend-container-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DonAdam2%2Fmicro-frontend-container-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DonAdam2%2Fmicro-frontend-container-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DonAdam2","download_url":"https://codeload.github.com/DonAdam2/micro-frontend-container-app/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229783791,"owners_count":18123557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react","react-router-dom","redux","webpack-module-federation","webpack5"],"created_at":"2024-12-15T05:17:58.541Z","updated_at":"2024-12-15T05:17:59.026Z","avatar_url":"https://github.com/DonAdam2.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Table of Contents:\n- [Overview](#micro-frontend-container)\n- [Prerequisites](#prerequisites)\n- [Installing \u0026 getting started](#installing--getting-started)\n- [How to import a remote module and use it](#how-to-import-a-remote-module-and-use-it)\n- [How to inject the remote module store slices into the current store](#how-to-inject-the-remote-module-store-slices-into-the-current-store)\n- [Available scripts](#available-scripts)\n\n## Micro frontend container\n\n- Uses ***module federation plugin*** from webpack to inject ***remote modules***.\n- This app is the host of [Micro frontend inner app](https://github.com/DonAdam2/micro-frontend-inner-app)\n\n**_Note:_** This app uses live reloading for local development.\n\n## Prerequisites\n\n- nodeJS \u003e 14.X.X or Docker\n\n## Installing / Getting Started\n\n### Development (locally):\n\n- Clone repo =\u003e `git clone git@github.com:react-custom-projects/webpack-react-boilerplate.git`\n- Navigate to project directory `cd webpack-react-boilerplate`\n- Install dependencies =\u003e `yarn install`\n- Start the development server =\u003e `yarn start`\n\n### Development (using Docker):\n\n- Clone repo =\u003e `git clone git@github.com:react-custom-projects/webpack-react-boilerplate.git`\n- Navigate to project directory `cd webpack-react-boilerplate`\n- Install dependencies (required for prettier) =\u003e `yarn install`\n- Start the development server =\u003e `docker-compose up web-dev`\n\n## Docker for production (_basic setup_) (modify it to your needs):\n- Update the **_production_** section of the **_Dockerfile_** to meet your needs\n- Run the following command to build your image =\u003e `docker-compose up web-prod`\n\n## How to import a _remote module_ and use it\n- Open **webpack.common.js** file.\u003cbr\u003e\n  1- Import ***ModuleFederationPlugin***:\n\n  ```\n  const { ModuleFederationPlugin } = require('webpack').container\n  ```\n\n  2- Pass ***ModuleFederationPlugin*** to the ***plugins*** array:\n\n  ```plugins: [\n  new ModuleFederationPlugin({\n  ```\n\n  3- Specify the name of the current app 678 in ***ModuleFederationPlugin***:\n\n  ```new ModuleFederationPlugin({\n  name: 'app_container',\n  ```\n\n  4- Add the link of the ***remote module*** in `remotes object` of the ***ModuleFederationPlugin***, example:\n\n  ```\n  new ModuleFederationPlugin({\n    remotes: {\n      inner_app: `inner_app@${isDevelopment ? remoteDevUrl : remoteProdUrl}/remoteEntry.js`,\n    },\n  ```\n\n  **_Notes:_**\n    - You must use the name of the ***remote module*** that you specified in the ***remote module*** webpack setup.\n    - You can add as many ***remote modules*** as you like by adding them to the `remotes object`\n    - **/buildTools/constants** contains ***remoteDevUrl*** and ***remoteProdUrl*** of the  ***remote module***.\n\n  5- Add the shared dependencies in ***ModuleFederationPlugin***:\n\n  ```\n  new ModuleFederationPlugin({\n    shared: ['react', 'react-dom'],\n  }),\n  ```\n\n  6- Install **external-remotes-plugin** and add it below ***ModuleFederationPlugin*** in the plugins array:\n\n  ```\n  //used to make sure that remote modules are loaded before the main bundle\n  new ExternalTemplateRemotesPlugin(),\n  ```\n\n- Import the ***remote module*** lazily in the required place, example:\n\n  ```\n  const RemoteApp = lazy(() =\u003e import('inner_app/App'));\n  ```\n\n- Use it inside ErrorBoundary component:\n\n  ```\n  \u003cErrorBoundary\n      FallbackComponent={RemoteEntryErrorBoundaryFallback}\n      onReset={() =\u003e {\n        //Reset the state of your app so the error doesn't happen again\n        console.log('Try again clicked');\n      }}\n    \u003e\n      \u003cSuspense\n        fallback={\n          \u003cdiv className=\"loader-wrapper\"\u003e\n            \u003cLoadingIcon /\u003e\n          \u003c/div\u003e\n        }\n      \u003e\n        \u003cRemoteApp /\u003e\n      \u003c/Suspense\u003e\n    \u003c/ErrorBoundary\u003e\n  ```\n\n## How to inject the _remote module_ store slices into the current store\n\n- Install `redux-dynamic-middlewares` package if the **remote module** has middle wares.\n\n- Open `/src/js/store/store.js` file:\n\n    1- Import `dynamicMiddlewares` from `redux-dynamic-middlewares` package:\n\n    ```\n    import dynamicMiddlewares from 'redux-dynamic-middlewares'\n    ```\n        \n    2- Import `configureStore`:\n\n    ```\n    import { configureStore } from '@reduxjs/toolkit';\n    ```\n            \n    3- Import your redux slices:\n    \n    ```\n    import { reducerSlices } from './reducerSlices';\n    ```\n    \n    4- Create your redux store and pass to it **dynamicMiddlewares**:\n    \n    ```\n    export default configureStore({\n      reducer: reducerSlices,\n      devTools: isDevelopment,\n      middleware: (getDefaultMiddleware) =\u003e {\n        if (isDevelopment) {\n          const { logger } = require('redux-logger'),\n            middlewares = [logger, dynamicMiddlewares];\n\n          return getDefaultMiddleware().concat(middlewares);\n        }\n\n        return getDefaultMiddleware();\n      },\n    });\n    ```\n\n    5- Add **createReducer** function:\n\n    ```\n    //used to merge dynamic reducer slices into static reducer slices\n    export const createReducer = (asyncReducers) =\u003e\n    combineReducers({\n      ...reducerSlices,\n      ...asyncReducers,\n    });\n    ```\n    \n- Open the component in which you want to use the imported module:\n    \n    1- Import `addMiddleware` from `redux-dynamic-middlewares` package:\n\n    ```\n    import { addMiddleware } from 'redux-dynamic-middlewares';\n    ```\n        \n    2- Import current app **store** and **createReducer** function:\n\n   ```\n    import store, { createReducer } from '@/js/store/store';\n   ```\n    \n    3- Import the `remote module` lazily:\n\n    ```\n    const RemoteApp = lazy(() =\u003e import('inner_app/App'));\n    ```\n    \n    2- Create **injectMiddleWares** function in the component:\n\n    ```\n    const injectMiddleWares = (middleWares) =\u003e {\n      middleWares.forEach((el) =\u003e addMiddleware(el));\n    };\n    ```\n\n    3- Create **injectSlices** function in the component:\n\n    ```\n    const injectSlices = (asyncReducerSlices) =\u003e {\n      let asyncReducers = {};\n      Object.entries(asyncReducerSlices).forEach((el) =\u003e (asyncReducers[el[0]] = el[1]));\n\n      store.replaceReducer(createReducer(asyncReducers));\n    };\n    ```\n        \n    4- Pass `store`, `injectSlices` and `injectMiddleWares` to the `remote module`:\n\n    ```\n    \u003cRemoteApp\n      injectMiddleWares={injectMiddleWares}\n      store={store}\n      injectSlices={injectSlices}\n    /\u003e\n    ```\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `yarn start`\n\nRuns the app in the development mode.\u003cbr\u003e\nIt will open [http://localhost:3000](http://localhost:3000) automatically in the browser to see your app.\n\nAll changes will be injected automatically without reloading the page.\u003cbr\u003e\n\nYou will see in the console the following:\n\n- All redux store related changes\n- Any of the following errors:\n  1. Linting errors.\n  2. Code format errors (because of [prettier](https://prettier.io/))\n\n### `yarn build`\n\nBuilds the app for production to the `dist` folder.\u003cbr\u003e\nIt correctly bundles React in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.\u003cbr\u003e\nYour app is ready to be deployed!\n\n### `yarn build:serve`\n\nServes the app on [http://localhost:8080](http://localhost:8080) from the `dist` folder to check the production version.\n\n**_Note:_** Use this script only if you ran the build script `yarn build`.\n\n### `yarn analyze-bundle`\n\nIt allows you to analyze the bundle size.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonadam2%2Fmicro-frontend-container-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdonadam2%2Fmicro-frontend-container-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonadam2%2Fmicro-frontend-container-app/lists"}