{"id":20817030,"url":"https://github.com/miteshtagadiya/microfrontend-react","last_synced_at":"2025-05-07T13:34:07.721Z","repository":{"id":95875442,"uuid":"248789085","full_name":"miteshtagadiya/microfrontend-react","owner":"miteshtagadiya","description":"Micro Front-end react apps created by Create-React-App, Connect multiple react apps to single parent app.","archived":false,"fork":false,"pushed_at":"2023-09-30T09:49:40.000Z","size":458,"stargazers_count":22,"open_issues_count":0,"forks_count":16,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-05-07T13:33:34.726Z","etag":null,"topics":["chunks","manifest","microfrontend","microfrontend-architecture","microfrontend-react","microfrontend-react-apps","microfrontends","microfrontends-demo","multiapp","react","react-component-wrapper","react-components","react-hooks","react-micro-apps","reactjs","reusable-components","split"],"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/miteshtagadiya.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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-20T15:27:45.000Z","updated_at":"2025-04-07T08:08:34.000Z","dependencies_parsed_at":"2025-05-07T13:31:17.167Z","dependency_job_id":null,"html_url":"https://github.com/miteshtagadiya/microfrontend-react","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/miteshtagadiya%2Fmicrofrontend-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miteshtagadiya%2Fmicrofrontend-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miteshtagadiya%2Fmicrofrontend-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miteshtagadiya%2Fmicrofrontend-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/miteshtagadiya","download_url":"https://codeload.github.com/miteshtagadiya/microfrontend-react/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252887415,"owners_count":21819894,"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":["chunks","manifest","microfrontend","microfrontend-architecture","microfrontend-react","microfrontend-react-apps","microfrontends","microfrontends-demo","multiapp","react","react-component-wrapper","react-components","react-hooks","react-micro-apps","reactjs","reusable-components","split"],"created_at":"2024-11-17T21:38:51.239Z","updated_at":"2025-05-07T13:34:07.710Z","avatar_url":"https://github.com/miteshtagadiya.png","language":"JavaScript","readme":"# microfrontend-react\nMicro Front-end react apps created by Create-React-App\n\nMicro-frontend architecture is a design approach in which a front-end app is decomposed into individual, semi-independent “microapps” working loosely together.\n\nTh applications are loaded into a micro-frontend container. The container runs it as of the micro frontend is its own component and provides seamless workflow to users.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"microfrontend.gif\"\u003e\n\u003c/p\u003e\n\n### This is the workflow of how micro front-ends work:\n- Launch container app.\n- Launch sub-app1 and sub-app2 applications on specific ports.\n- Based on the URL, the Container will route to one of the micro front-ends.\n- The selected micro front-end goes to the specific port to fetch the application’s asset-manifest.json. From this JSON file, the included main.js is put on a script tag and loaded.\n- A manifest file contains a mapping of all asset filenames.\n- Container app passes the containerId and history for its micro front-ends to be rendered.\n\n### Start creating micro front-end apps:\n- Install \"react-app-rewired\" — This allows customizing the app without ejecting app.\n```jsx\nnpm i --save react-app-rewired\n```\n- Modify package.json to set port and use \"react-app-rewired\" in sub-apps.\n```jsx\n \"scripts\": {\n   \"start\": \"PORT=4001 react-app-rewired start\",\n   \"build\": \"react-app-rewired build\",\n   \"test\": \"react-app-rewired test\",\n   \"eject\": \"react-app-rewired eject\"\n },\n```\n- Add config-overrides.js to disable code splitting. By default, code splitting is enabled. An application is split into several chunks that can be loaded onto the page independently. You can see http://localhost:4001/asset-manifest.json before adding react-app-rewired. It clearly shows the app has been chunked.\n```jsx\n//config-overrides.js\nmodule.exports = {\n  webpack: (config, env) =\u003e {\n    config.optimization.runtimeChunk = false;\n    config.optimization.splitChunks = {\n      cacheGroups: {\n        default: false,\n      },\n    };\n    return config;\n  },\n};\n```\n- Make changes in src/index.js to define render and unmount functions.\n```jsx\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./index.css\";\nimport App from \"./App\";\nimport * as serviceWorker from \"./serviceWorker\";\n\n// render micro frontend function\nwindow.rendersubapp1 = (containerId, history) =\u003e {\n  ReactDOM.render(\n    \u003cApp history={history} /\u003e,\n    document.getElementById(containerId)\n  );\n  serviceWorker.unregister();\n};\n\n// unmount micro frontend function\nwindow.unmountsubapp1 = containerId =\u003e {\n  ReactDOM.unmountComponentAtNode(document.getElementById(containerId));\n};\n\n// Mount to root if it is not a micro frontend\nif (!document.getElementById(\"subapp1-container\")) {\n  ReactDOM.render(\u003cApp /\u003e, document.getElementById(\"root\"));\n}\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n```\n- If an app is running independent, it will be rendered to root element. If it is a micro front-end, it will be rendered to containerId by window.rendersubapp1.\n- Use src/setupProxy.js to set up CORS rule.\n```jsx\nmodule.exports = app =\u003e {\n  app.use((req, res, next) =\u003e {\n    res.header('Access-Control-Allow-Origin', '*');\n    next();\n  });\n};\n```\n- Configure Your .env File to Set Up a Host for Each Micro-Frontend Application in Container app.\n```jsx\nREACT_APP_SUBAPP1_HOST=http://localhost:4001\nREACT_APP_SUBAPP2_HOST=http://localhost:4002\n```\n- Add Microfront.js file in sec directory, It picks up a manifest file from a running application and launches the application through a script and link tag.\n```jsx\nimport React from 'react';\n\nclass MicroFrontend extends React.Component {\n  componentDidMount() {\n    const { name, host, document } = this.props;\n    const scriptId = `micro-frontend-script-${name}`;\n\n    if (document.getElementById(scriptId)) {\n      this.renderMicroFrontend();\n      return;\n    }\n\n    fetch(`${host}/asset-manifest.json`)\n      .then(res =\u003e res.json())\n      .then(manifest =\u003e {\n        manifest[\"entrypoints\"].map((entry =\u003e {\n          if (typeof manifest[\"files\"][entry] !== \"undefined\" \u0026\u0026 manifest[\"files\"][entry] !== \"undefined\") {\n            if (entry.endsWith('.css')) {\n              const link = document.createElement('link');\n              link.id = scriptId;\n              link.href = `${process.env.NODE_ENV === \"production\" ? host.slice(0, host.lastIndexOf('/')) : host}${manifest[\"files\"][entry]}`;\n              link.onload = this.renderMicroFrontend;\n              link.rel = \"stylesheet\"\n              document.head.appendChild(link);\n            }\n            const script = document.createElement('script');\n            script.id = scriptId;\n            script.crossOrigin = '';\n            script.src = `${process.env.NODE_ENV === \"production\" ? host.slice(0, host.lastIndexOf('/')) : host}${manifest[\"files\"][entry]}`;\n            script.onload = this.renderMicroFrontend;\n            document.head.appendChild(script);\n          }\n        })\n        )\n        const script = document.createElement('script');\n        script.id = scriptId;\n        script.crossOrigin = '';\n        script.src = `${process.env.NODE_ENV === \"production\" ? host.slice(0, host.lastIndexOf('/')) : host}${manifest[\"files\"][\"main.js\"]}`;\n        script.onload = this.renderMicroFrontend;\n        document.head.appendChild(script);\n        const link = document.createElement('link');\n        link.id = scriptId;\n        link.href = `${process.env.NODE_ENV === \"production\" ? host.slice(0, host.lastIndexOf('/')) : host}${manifest[\"files\"][\"main.css\"]}`;\n        link.onload = this.renderMicroFrontend;\n        link.rel = \"stylesheet\"\n        document.head.appendChild(link);\n      });\n  }\n\n  componentWillUnmount() {\n    const { name, window } = this.props;\n\n    window[`unmount${name}`] \u0026\u0026 window[`unmount${name}`](`${name}-container`);\n  }\n\n  renderMicroFrontend = () =\u003e {\n    const { name, window, history } = this.props;\n\n    window[`render${name}`] \u0026\u0026 window[`render${name}`](`${name}-container`, history);\n  };\n\n  render() {\n    return \u003cmain id={`${this.props.name}-container`} /\u003e;\n  }\n}\n\nMicroFrontend.defaultProps = {\n  document,\n  window,\n};\n\nexport default MicroFrontend;\n```\n- In Container App Create a Micro-Frontend Component for each micro-frontend application and Use a route to invoke it.\n```jsx\nimport React from \"react\";\nimport { NavLink, BrowserRouter, Route, Switch } from \"react-router-dom\";\nimport MicroFrontend from \"./MicroFrontend\";\n\nconst {\n  REACT_APP_SUBAPP1_HOST: subapp1,\n  REACT_APP_SUBAPP2_HOST: subapp2\n} = process.env;\n\nconst SubApp2 = ({ history }) =\u003e (\n  \u003cMicroFrontend history={history} host={subapp2} name=\"subapp2\" /\u003e\n);\n\nconst SubApp1 = ({ history }) =\u003e (\n  \u003cMicroFrontend history={history} host={subapp1} name=\"subapp1\" /\u003e\n);\n\nconst Home = () =\u003e (\n  \u003c\u003e\n    \u003cp\u003eRendered by Container\u003c/p\u003e\n  \u003c/\u003e\n);\n\nconst App = props =\u003e {\n  return (\n    \u003cBrowserRouter\u003e\n      \u003cdiv style={{ padding: 25, display: \"flex\" }}\u003e\n        \u003cdiv style={{ padding: \"0px 15px\" }}\u003e\n          \u003cNavLink\n            style={{\n              textDecoration: \"none\",\n              fontWeight: \"bold\",\n              color: \"#282c34\",\n              fontSize: 20\n            }}\n            to=\"/home\"\n          \u003e\n            Home\n          \u003c/NavLink\u003e\n        \u003c/div\u003e\n        \u003cdiv style={{ padding: \"0px 15px\" }}\u003e\n          \u003cNavLink\n            style={{\n              textDecoration: \"none\",\n              fontWeight: \"bold\",\n              color: \"#282c34\",\n              fontSize: 20\n            }}\n            to=\"/subapp1\"\n          \u003e\n            SubApp1\n          \u003c/NavLink\u003e\n        \u003c/div\u003e\n        \u003cdiv style={{ padding: \"0px 15px\" }}\u003e\n          \u003cNavLink\n            style={{\n              textDecoration: \"none\",\n              fontWeight: \"bold\",\n              color: \"#282c34\",\n              fontSize: 20\n            }}\n            to=\"/subapp2\"\n          \u003e\n            SubApp2\n          \u003c/NavLink\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n\n      \u003cSwitch\u003e\n        \u003cRoute path=\"/home\" component={Home} /\u003e\n        \u003cRoute path=\"/subapp1\" render={() =\u003e \u003cSubApp1 /\u003e} /\u003e\n        \u003cRoute path=\"/subapp2\" render={() =\u003e \u003cSubApp2 /\u003e} /\u003e\n      \u003c/Switch\u003e\n    \u003c/BrowserRouter\u003e\n  );\n};\n\nexport default App;\n```\n### Run miro front-end Apps:\n```jsx\nContainer App: http://localhost:3000\nSubApp1: http://localhost:4001\nSubApp2: http://localhost:4002\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiteshtagadiya%2Fmicrofrontend-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmiteshtagadiya%2Fmicrofrontend-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiteshtagadiya%2Fmicrofrontend-react/lists"}