{"id":13847333,"url":"https://github.com/unadlib/fronts","last_synced_at":"2025-04-05T06:09:37.868Z","repository":{"id":39002115,"uuid":"194525766","full_name":"unadlib/fronts","owner":"unadlib","description":"A progressive  micro frontends framework for building Web applications","archived":false,"fork":false,"pushed_at":"2024-01-31T16:49:50.000Z","size":6138,"stargazers_count":485,"open_issues_count":120,"forks_count":51,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-29T05:09:22.759Z","etag":null,"topics":["angular","front-end","frontend","javascript","micro-frontends","micro-frontends-solution","microfrontends","microservices","mircofrontend","module-federation","react","vue"],"latest_commit_sha":null,"homepage":"https://fronts.js.org/","language":"TypeScript","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/unadlib.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}},"created_at":"2019-06-30T14:32:33.000Z","updated_at":"2025-03-12T08:09:47.000Z","dependencies_parsed_at":"2024-01-15T20:49:28.850Z","dependency_job_id":"c2afa74e-708e-4ca2-adc6-70fca66a00b4","html_url":"https://github.com/unadlib/fronts","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Ffronts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Ffronts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Ffronts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Ffronts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unadlib","download_url":"https://codeload.github.com/unadlib/fronts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294541,"owners_count":20915340,"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":["angular","front-end","frontend","javascript","micro-frontends","micro-frontends-solution","microfrontends","microservices","mircofrontend","module-federation","react","vue"],"created_at":"2024-08-04T18:01:17.041Z","updated_at":"2025-04-05T06:09:37.832Z","avatar_url":"https://github.com/unadlib.png","language":"TypeScript","readme":"\u003ca href=\"https://fronts.js.org/\" target=\"_blank\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/unadlib/fronts/master/website/static/img/logo.svg\" height=\"96\" alt=\"Fronts Logo\" /\u003e\u003c/a\u003e\n\n---\n\n![Node CI](https://github.com/unadlib/fronts/workflows/Node%20CI/badge.svg)\n[![npm version](https://badge.fury.io/js/fronts.svg)](http://badge.fury.io/js/fronts)\n![license](https://img.shields.io/npm/l/fronts)\n\nFronts is a progressive micro frontends framework for building Web applications, and it's based on the [module federation](https://webpack.js.org/concepts/module-federation/) of Webpack.\n\n## Motivation\n\nAmong the many micro frontends solutions, [single-spa](https://github.com/single-spa/single-spa) and [Module Federation](https://webpack.js.org/concepts/module-federation/) are the best of them.\n\n[single-spa](https://github.com/single-spa/single-spa) is a micro frontends framework based on router configuration. The centralization of configuration brings some limitations, such as it is difficult to granulate nestable micro frontends, module granularity control, module sharing, and so on.\n\nIn 2019, Zack Jackson proposed and implemented Module Federation. Module Federation is a completely different concept from single-spa, and allows a JavaScript application to dynamically load code from another application. It completely solves the problem of code dependency sharing and runtime modularity. The idea is true - [A game-changer in JavaScript architecture](https://medium.com/swlh/webpack-5-module-federation-a-game-changer-to-javascript-architecture-bcdd30e02669) as mentioned in Zack Jackson's article. And it's currently supported by Webpack, Next.js, and Rollup.\n\nAlthough the Module Federation concept is so amazing, it has not yet gone further to provide a more complete and fully targeted micro frontends framework implementation, and this is what Fronts is trying to do.\n\n## Features\n\n- **Non-module-federation** - Although Fronts is based on the concept of module federation, it also supports `non-module-federation` mode.\n- **Decentralized configuration** - Configure `site.json` for dependency management in each Fronts app, support for nested micro frontends.\n- **Cross frameworks** - No framework or technology stack is restricted.\n- **Code splitting \u0026 lazy loading** - Support code splitting within the Fronts app as a module, it can be lazy loaded by other Fronts app as a dependent module.\n- **CSS isolation** - Optional CSS isolation solution.\n- **Lifecycle** - Fronts provide concise lifecycle for Fronts app entry.\n- **Web Components \u0026 iFrame** - Support for multiple frontend containers.\n- **Multiple patterns** - Support for building `micro-frontends` app and `non-micro-frontends` app.\n- **Monorepo \u0026 TypeScript** - Friendly support for Monorepo and TypeScript, which are mutually appropriate technology stack.\n- **Version control** - It's used for efficient and dynamic delivery apps such as canary release.\n- **Zero hijacking** - Fronts didn't do any hijacking, maintaining originality and possible loss of performance and security.\n- **Generic Communication** - Fronts provides concise and generic communication APIs, which supports almost all frontend environments.\n\n## Getting Started\n\n\u003e You can follow this article([React without create-react-app Webpack 5](https://dev.to/rogeliosamuel621/react-without-create-react-app-webpack-5-1b1o)) to quickly create `app1` and `app2` React projects.\n\nAssuming you've completed these steps, let's get started with a quick taste of the wonderful micro frontends development of Fronts.\n\n1. Install `fronts-react` and `fronts-bundler` in the projects.\n\n```shell\n# with NPM\nnpm install fronts-react fronts-bundler\n\n# or with Yarn\nyarn add fronts-react fronts-bundler\n```\n\n2. Set up `site.json` and `webpack.config.js` in the projects\n\nWe define `app1` as a parent micro frontend and it depends on `app2`.\n\n`app1/site.json`:\n\n```json\n{\n  \"name\": \"app1\",\n  \"exports\": [],\n  \"dependencies\": {\n    \"app2\": \"http://localhost:3002/remoteEntry.js\"\n  }\n}\n```\n\n`app2` doesn't have any dependencies, it acts as a micro frontend and we define it to export `./src/bootstrap` as a micro frontends entry, this entry of `app2` end will be used by `app1`.\n\n`app2/site.json`:\n\n```json\n{\n  \"name\": \"app2\",\n  \"exports\": [\"./src/bootstrap\"],\n  \"dependencies\": {}\n}\n```\n\nWrap the Webpack config with `createWebpackConfig()` in `config/webpack.config.js` in the projects.\n\n```js\nconst { createWebpackConfig } = require('fronts-bundler');\n\nmodule.exports = createWebpackConfig(originalWebpackConfig);\n```\n\n3. Define the default exported bootstrap function in `app2/src/bootstrap.jsx` and use `boot()` to get it booted.\n\n```jsx\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport { boot } from 'fronts-react';\nimport App from './App';\n\nexport default function render(element) {\n  ReactDOM.render(\u003cApp /\u003e, element);\n  return () =\u003e {\n    ReactDOM.unmountComponentAtNode(element);\n  };\n}\n\nboot(render, document.getElementById('root'));\n```\n\n4. Load `app1/src/App.jsx` with `useApp()` to import `app2`.\n\n```jsx\nimport React from 'react';\nimport { useApp } from 'fronts-react';\n\nexport const App = () =\u003e {\n  const App2 = useApp({\n    name: 'app2',\n    loader: () =\u003e import('app2/src/bootstrap'),\n  });\n  return \u003cApp2 /\u003e;\n};\n```\n\n## Examples\n\n- [Simple Example](https://github.com/unadlib/fronts-example)\n\n## APIs\n\n| API                  |      Isolation      |\n| :------------------- | :-----------------: |\n| `useApp()`           | CSS(loose/optional) |\n| `useWebComponents()` |         CSS         |\n| `useIframe()`        |   CSS, JavaScript   |\n\n### Built-in packages\n\nThe most popular frontend frameworks are React, Vue and Angular. When the micro frontends uses one of these frameworks, it is recommended to use Fronts built-in package for this framework, such as `fronts-react`, `fronts-vue` and `fronts-ng`, otherwise please use `fronts`.\n\n| Packages        | Support Framework |         Status |\n| :-------------- | :---------------: | -------------: |\n| `fronts`        |   Any Framework   |   Completed ✅ |\n| `fronts-react`  |       React       |   Completed ✅ |\n| `fronts-vue`    |        Vue        | In Progress 💡 |\n| `fronts-ng`     |      Angular      |              - |\n| `fronts-svelte` |      svelte       |              - |\n| `fronts-solid`  |      svelte       |              - |\n\n## Running Type\n\n| Type                  |                 Requirement                 |                                                              Support |\n| :-------------------- | :-----------------------------------------: | -------------------------------------------------------------------: |\n| Non-Module-Federation |                      -                      | Dependency Management ❌\u003cbr/\u003e Monorepo ❌\u003cbr/\u003e Version Management ❌ |\n| Module Federation     |           Webpack\u003cbr /\u003esite.json            | Dependency Management ✅\u003cbr/\u003e Monorepo ✅\u003cbr/\u003e Version Management ❌ |\n| Version Control       | Webpack\u003cbr /\u003esite.json\u003cbr /\u003eRegistry Server | Dependency Management ✅\u003cbr/\u003e Monorepo ✅\u003cbr/\u003e Version Management ✅ |\n\n## Debugger/Logger\n\nUse `getMeta()`, it helps you to get the dependency mapping information.\n\n```js\nimport { getMeta } from 'fronts';\n\nconsole.log(getMeta());\n\n// {\n//   \"name\": \"app3\",\n//   \"meta\": {\n//       \"__main__\": \"app1\",\n//       \"__entry__\": \"http://localhost:3001/#/app2\",\n//       \"app2\": {\n//           \"dependencies\": {\n//               \"app3\": \"http://localhost:3003\"\n//           }\n//       },\n//       \"app5\": {\n//           \"dependencies\": {\n//               \"app6\": \"http://localhost:3006\"\n//           }\n//       },\n//       \"app3\": {\n//           \"dependencies\": {}\n//       },\n//       \"app6\": {\n//           \"dependencies\": {}\n//       },\n//       \"app1\": {\n//           \"dependencies\": {\n//               \"app2\": \"http://localhost:3002\",\n//               \"app4\": \"http://localhost:3004\",\n//               \"app5\": \"http://localhost:3005\"\n//           }\n//       }\n//   }\n// }\n```\n\n## Testing\n\n`fronts-test` provides an runner for function step, and any micro frontends IT and E2E can use it for reusable testing. It also provides other APIs, such as `useContext()`, beforeHook and afterHook in `createRunner()`.\n\n```ts\nimport { $, useContext, Given, When, Then } from 'fronts-test';\n\nconst addTodo = $(() =\u003e {\n  const { page } = useContext();\n  await page.type('.text', 'Use Fronts');\n  await page.click('.add');\n});\n\ntest('base', async () =\u003e {\n  await Given('user open the page').then(entry);\n  await When('user add todo text').then(addTodo);\n  await Then('user should see that todo list has a new item').then(checkTodo);\n});\n```\n\n## CLI\n\ntodo\n\n## Version Control\n\nSet up the registry server URL in the `registry` field.\n\n\u003e It supports dynamic `import()`, and it does not support static import.\n\n```diff\n{\n  \"name\": \"app1\",\n  \"exports\": [],\n+ \"registry\": \"http://localhost:3000/dev.json\",\n  \"dependencies\": {\n-    \"app2\": \"http://localhost:3002/remoteEntry.js\"\n+    \"app2\": \"1.0.0\"\n  }\n}\n```\n\nStart the registry server and make sure that `http://localhost:3000/dev.json?scope=app2%401.0.0` request gets a response data with the version specification.\n\n```json\n{\n  \"app2\": \"http://localhost:3002/remoteEntry.js\"\n}\n```\n\n## Tutorial\n\ntodo\n\n## Q\u0026A\n\nQ: Can Non-Module-Federation, Module Federation, and Version Control be compatible with each other?\n\nA: Yes\n\nQ: How to use SPA development mode in micro frontends codebase?\n\nA: Use `SPA=true yarn start` instead of `yarn start`, make sure the current codebase is Monorepo and module federation or version control is enabled, and it just works with `useApp()` and `useWebComponent()`.\n\n## License\n\nFronts is MIT licensed.\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funadlib%2Ffronts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funadlib%2Ffronts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funadlib%2Ffronts/lists"}