{"_id":"@billy-briggs-dev/module-federation-tools","name":"@billy-briggs-dev/module-federation-tools","dist-tags":{"latest":"15.0.4"},"versions":{"15.0.4":{"name":"@billy-briggs-dev/module-federation-tools","version":"15.0.4","license":"MIT","peerDependencies":{"@angular/common":">=15.0.0","@angular/core":">=15.0.0","@angular/router":">=15.0.0","@billy-briggs-dev/module-federation":"^15.0.4","@angular/platform-browser":">=15.0.0","rxjs":">= 6.0.0"},"dependencies":{"tslib":"^2.0.0"},"module":"fesm2015/billy-briggs-dev-module-federation-tools.mjs","es2020":"fesm2020/billy-briggs-dev-module-federation-tools.mjs","esm2020":"esm2020/billy-briggs-dev-module-federation-tools.mjs","fesm2020":"fesm2020/billy-briggs-dev-module-federation-tools.mjs","fesm2015":"fesm2015/billy-briggs-dev-module-federation-tools.mjs","typings":"index.d.ts","exports":{"./package.json":{"default":"./package.json"},".":{"types":"./index.d.ts","esm2020":"./esm2020/billy-briggs-dev-module-federation-tools.mjs","es2020":"./fesm2020/billy-briggs-dev-module-federation-tools.mjs","es2015":"./fesm2015/billy-briggs-dev-module-federation-tools.mjs","node":"./fesm2015/billy-briggs-dev-module-federation-tools.mjs","default":"./fesm2020/billy-briggs-dev-module-federation-tools.mjs"}},"sideEffects":false,"gitHead":"03cb3d3e6ee89bb4c08ecec4d320076326d6e426","description":"Add-on for `@angular-architects/module-federation` helping to reduce boiler plate code.","_id":"@billy-briggs-dev/module-federation-tools@15.0.4","_nodeVersion":"16.19.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-ffX8gPtrf1LNbCNZR8Uf6pFSSNuUaqDBAON83q9TyNmDZGRkYQ0OYtk9g7sVGSrk1+Dlp82LuTWjqeXs/L+Ajw==","shasum":"6b17ca319cef7bb30bd73538b259820c21e3a71c","tarball":"https://registry.npmjs.org/@billy-briggs-dev/module-federation-tools/-/module-federation-tools-15.0.4.tgz","fileCount":20,"unpackedSize":108434,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD2Ot54uGJq0fawopuiS4ZcyjPcGbO70ecwxd8/iG6DOgIhAKjBAw/HbEkAG1KiQKHVv5PaWDZdm0wvf6aK7N3nxa43"}]},"_npmUser":{"name":"billy-briggs-dev","email":"billybriggs33@gmail.com"},"directories":{},"maintainers":[{"name":"billy-briggs-dev","email":"billybriggs33@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/module-federation-tools_15.0.4_1701127360825_0.7438378334158293"},"_hasShrinkwrap":false}},"time":{"created":"2023-11-27T23:22:40.754Z","15.0.4":"2023-11-27T23:22:41.132Z","modified":"2023-11-27T23:22:41.417Z"},"maintainers":[{"name":"billy-briggs-dev","email":"billybriggs33@gmail.com"}],"description":"Add-on for `@angular-architects/module-federation` helping to reduce boiler plate code.","license":"MIT","readme":"# @angular-architects/module-federation-tools\n\nAdd-on for `@angular-architects/module-federation` helping to reduce boiler plate code.\n\nThe current release is focusing on combining web components with module federation for **multi framework and multi version** micro frontends:\n\n![Example](https://i.ibb.co/CHBQn5j/example.png)\n\nBy compiling and loading these **web components via module federation**, we can share libraries like Angular if they use the same version. Otherwise, module federation would decide at runtime to load a dedicated version of the lib for the micro frontend in question:\n\n![Venn](https://www.angulararchitects.io/wp-content/webp-express/webp-images/doc-root/wp-content/uploads/2020/12/venn.png.webp)\n\nThis can help to **balance the trade-off** between bundle size and isolation of micro frontends.\n\n> **Disclaimer:** Multi-Framework and -Version Micro increase the overall complexity and call for some workarounds. This library tries to hide some of them.\n\n## Features\n\n- ✅ **Minimal amount** of helper functions to allow implementing multi-framework/ multi-version Micro Frontends with Module Federation\n- ✅ You don't need an additional meta-framework. Instead, you just use your framework of choice, e. g. Angular\n- ✅ Extension to [@angular-architects/module-federation](https://www.npmjs.com/package/@angular-architects/module-federation)\n\n## Examples\n\n- [Live Example](https://red-ocean-0fe4c4610.azurestaticapps.net)\n- [Source Code Shell](https://github.com/manfredsteyer/multi-framework-version)\n- [Source Code for Micro Frontend](https://github.com/manfredsteyer/angular-app1)\n- [Source Code for Micro Frontend with Routing](https://github.com/manfredsteyer/angular3-app)\n- [Source Code for Micro Frontend with Vue](https://github.com/manfredsteyer/vue-js)\n- [Source Code for Micro Frontend with React](https://github.com/manfredsteyer/react-app)\n- [Source Code for Micro Frontend with AngularJS](https://github.com/manfredsteyer/angularjs-app)\n\n## Tutorial\n\nPlease find our [tutorial here](https://github.com/angular-architects/module-federation-plugin/blob/main/libs/mf-tools/tutorial/index.md).\n\n## Providing a Web Component with Module Federation\n\nThis helper packages assumes that Micro Frontends are exposed as Web Components.\n\n### Exposing Micro Frontend as Web Component in Angular\n\nTo do this in Angular, install `@angular/elements`:\n\n```bash\nnpm i @angular/elements\n```\n\nThen you can directly convert your AppComponent to a Web Component:\n\n```typescript\nimport { createCustomElement } from '@angular/elements';\n[...]\n\n@NgModule({\n  [...]\n  declarations: [\n    AppComponent\n  ],\n  bootstrap: [] // No bootstrap components!\n})\nexport class AppModule {\n  constructor(private injector: Injector) {\n  }\n\n  ngDoBootstrap() {\n    const ce = createCustomElement(AppComponent, {injector: this.injector});\n    customElements.define('angular1-element', ce);\n  }\n\n}\n```\n\n### Exposing Web Component with other Frameworks like React\n\nIf you framework doesn't directly support exposing your application as a web component, you can easily write a simple Wrapper around it. Basically, a web component -- to be more precise: a custom element -- is just an EcmaScript class extending `HtmlElement` and registered via `customElements.register`. Please find an [example for React here](https://github.com/manfredsteyer/react-app/blob/main/app.js).\n\n### Exposing Web Component-based Micro Frontend via Module Federation\n\nAdd `@angular-architects/module-federation` to your micro frontend:\n\n```\nng add @angular-architects/module-federation\n```\n\nMake your `webpack.config.js` expose the whole `bootstrap.ts` that bootstraps your `AppModule`.\n\n```typescript\n// webpack.config.js\nname: \"angular3\",\nlibrary: { type: \"var\", name: \"angular3\" },\nfilename: \"remoteEntry.js\",\nexposes: {\n    './web-components': './src/bootstrap.ts',\n},\n```\n\nIf the file that bootstraps your applications is called differently, adjust these settings accordingly.\n\n## Helper for Angular\n\nFor enabling Angular for a multi version/ multi framework scenario, we need some helper functions. The easiest way to use them, is to bootstrap your Angular app with our bootstrap helper:\n\n```typescript\n// main.ts\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\nimport { bootstrap } from '@angular-architects/module-federation-tools';\n\nbootstrap(AppModule, {\n  production: environment.production,\n  appType: 'shell',\n  // appType: 'microfrontend'\n});\n```\n\n> Use this bootstrap helper for **both**, your shell and your micro frontends!\n\nPlease make sure to set the `appType` to `shell` for your shell application and to `microfrontend` for your Micro Frontends.\n\n## Routing to Web Components\n\nThe `WebComponentWrapper` helps you to route to web components:\n\n```typescript\nexport const APP_ROUTES: Routes = [\n    [...]\n    {\n        path: 'angular1',\n        component: WebComponentWrapper,\n        data: {\n          remoteEntry: 'https://nice-grass-018f7d910.azurestaticapps.net/remoteEntry.js',\n          remoteName: 'angular1',\n          exposedModule: './web-components',\n          elementName: 'angular1-element'\n        } as WebComponentWrapperOptions\n    },\n    [...]\n}\n```\n\n### Important: Angular 13+\n\nBeginning with Angular 13, the CLI is emitting EcmaScript modules. Hence, we need to adjust the usage of the WebComponentWrapper when loading a remote that has been created with the CLI 13 or higher. For this, set `type` to `remote` and skip the `remoteName` property (for Modules, we don't need a remoteName):\n\n```typescript\nexport const APP_ROUTES: Routes = [\n    [...]\n    {\n        path: 'angular1',\n        component: WebComponentWrapper,\n        data: {\n          type: 'module',\n          remoteEntry: 'https://your-path/remoteEntry.js',\n          exposedModule: './web-components',\n          elementName: 'angular1-element'\n        } as WebComponentWrapperOptions\n    },\n    [...]\n}\n```\n\n## Sub-Routes\n\nIf a web component has it's own router, you can use our UrlMatchers `startsWith` and `endsWith` to define, which part of the URL is intended for the shell and for the micro frontend:\n\n```typescript\n// Shell\nexport const APP_ROUTES: Routes = [\n    [...]\n    {\n        matcher: startsWith('angular3'),\n        component: WebComponentWrapper,\n        data: {\n          remoteEntry: 'https://gray-river-0b8c23a10.azurestaticapps.net/remoteEntry.js',\n          remoteName: 'angular3',\n          exposedModule: './web-components',\n          elementName: 'angular3-element'\n        } as WebComponentWrapperOptions\n    },\n    [...]\n}\n```\n\n```typescript\n// Micro Frontend\nRouterModule.forRoot([\n  { path: 'angular3/a', component: AComponent },\n  { path: 'angular3/b', component: BComponent },\n\n  // To prevent issues when routing to other micro frontends\n  // a catch-all route should be defined\n  { path: '**', component: EmptyComponent },\n]);\n```\n\n## Directly Loading a Web Component via Module Federation\n\nThe `WebComponentWrapper` can also be used as a traditional component:\n\n```html\n<mft-wc-wrapper [options]=\"item\"></mft-wc-wrapper>\n```\n\n```typescript\nitem: WebComponentWrapperOptions = {\n    remoteEntry: 'https://witty-wave-0a695f710.azurestaticapps.net/remoteEntry.js',\n    remoteName: 'react',\n    exposedModule: './web-components',\n    elementName: 'react-element'\n},\n```\n\nThe optional properties `props` and `events` allow to defined properties and events for the web component:\n\n```typescript\nprops = {\n  message: 'Hello from Shell',\n};\n\nevents = {\n  clicked: (event) => {\n    console.debug('clicked!', event);\n  },\n};\n```\n\n```html\n<mft-wc-wrapper\n  [options]=\"item\"\n  [props]=\"props\"\n  [events]=\"events\"\n></mft-wc-wrapper>\n```\n\n## Some Additional Details\n\n> In a multi version micro frontend strategy, it is important to load the zone.js bundle to the window object only once. Also, one need to make sure that only one instance of the ngZone is used by all the micro frontends.\n\nIf you share `@angular/core` and therefore also have one technical reference to the BrowserPlatform, that is used by more than one micro frondend, Angular's default setup is, to support only one platform instance per shared version. Be aware that you **need** to create multi platform instances in case of different versions, but also in case the version is the same, but `@angular/core` is not shared, but packed into the micro frontend's bundles directly (like in Angular's default way w/o module federation).\n\nNaturally, such technical details are hard to get into. Therefore the `bootstrap()` function of this package helps to implement your multi version strategy w/o the need of implementing those low-level aspects on your own.\n\nSome optional flags are offered to provide options for custom behavior of the `bootstrap()` function:\n\n- `ngZoneSharing: false`: Deactivate ngZone sharing in the window object (not recommended):\n  ```typescript\n  bootstrap(AppModule, {\n    production: environment.production,\n    ngZoneSharing: false, // defaults to true\n  });\n  ```\n- `platformSharing: false`: Deactivate Platform sharing in the window object (not recommended):\n  ```typescript\n  bootstrap(AppModule, {\n    production: environment.production,\n    platformSharing: false, // defaults to true\n  });\n  ```\n  - Possible, if dependencies are not shared or each bootstrapped remote app uses a different version.\n- `activeLegacyMode: false`: Deactivates the legacy mode that provides backwards compatibility for Platform sharing:\n  ```typescript\n  bootstrap(AppModule, {\n    production: environment.production,\n    activeLegacyMode: false, // defaults to true\n  });\n  ```\n  - If all your micro frontends use `@angular-architects/module-federation-tools` in version `^12.6.0`, `^13.1.0` or any newer major version you can switch off the legacy mode manually.\n  - Those versions introduced new features on how to share the Platform in the window object.\n  - This allows to use the `bootstrap()` function even in such cases, where the same version is packed into different micro frontend bundles.\n\n## More about the underlying ideas\n\nPlease find more information on the underlying ideas in this [blog article](https://www.angulararchitects.io/aktuelles/multi-framework-and-version-micro-frontends-with-module-federation-the-good-the-bad-the-ugly).\n","readmeFilename":"README.md"}