diff --git a/libs/mf-runtime/package.json b/libs/mf-runtime/package.json index a60add2a..061c4281 100644 --- a/libs/mf-runtime/package.json +++ b/libs/mf-runtime/package.json @@ -1,10 +1,10 @@ { "name": "@angular-architects/module-federation-runtime", "license": "MIT", - "version": "14.3.0-beta.4", + "version": "14.3.0", "peerDependencies": { - "@angular/common": ">=14.0.0-next.15", - "@angular/core": ">=14.0.0-next.15" + "@angular/common": ">=14.0.0", + "@angular/core": ">=14.0.0" }, "dependencies": { "tslib": "^2.0.0" diff --git a/libs/mf-tools/package.json b/libs/mf-tools/package.json index b7b60913..f0dc6fdb 100644 --- a/libs/mf-tools/package.json +++ b/libs/mf-tools/package.json @@ -1,13 +1,13 @@ { "name": "@angular-architects/module-federation-tools", - "version": "14.3.0-beta.4", + "version": "14.3.0", "license": "MIT", "peerDependencies": { - "@angular/common": ">=14.0.0-next.15", - "@angular/core": ">=14.0.0-next.15", - "@angular/router": ">=14.0.0-next.15", - "@angular-architects/module-federation": "^14.3.0-beta.4", - "@angular/platform-browser": ">=14.0.0-next.15", + "@angular/common": ">=14.0.0", + "@angular/core": ">=14.0.0", + "@angular/router": ">=14.0.0", + "@angular-architects/module-federation": "^14.3.0", + "@angular/platform-browser": ">=14.0.0", "rxjs": ">= 6.0.0" }, "dependencies": { diff --git a/libs/mf/README.md b/libs/mf/README.md index 30bd89d9..f9beb148 100644 --- a/libs/mf/README.md +++ b/libs/mf/README.md @@ -8,10 +8,11 @@ Big thanks to the following people who helped to make this possible: - [Tobias Koppers](https://twitter.com/wSokra), Founder of Webpack - [Dmitriy Shekhovtsov](https://twitter.com/valorkin), Angular GDE +- [Michael Egger-Zikes](https://twitter.com/MikeZks), Angular Architects ## Prequisites -- Angular CLI 12 +- Angular CLI 12 or higher (13, 14) ## Motivation ๐ฅ @@ -36,10 +37,21 @@ Since Version 1.2, we also provide some advanced features like: ## Which Version to use? - Angular 12: @angular-architects/module-federation: ^12.0.0 -- Angular 13: @angular-architects/module-federation: ^14.0.0 +- Angular 13: @angular-architects/module-federation: ~14.2.0 +- Angular 14: @angular-architects/module-federation: ^14.3.0 Beginning with Angular 13, we had to add some changes to adjust to the Angular CLI. Please see the next section for this. +## Update + +This library supports ``ng update``: + +``` +ng update @angular-architects/module-federation +``` + +If you update by hand (e. g. via ``npm install``), make sure you also install a respective version of ngx-build-plus (version 14 for Angular 14, version 13 for Angular 13, etc.) + ## Upgrade from Angular 12 or lower Beginning with Angular 13, the CLI generates EcmaScript modules instead of script files. This affects how we work with Module Federation a bit. @@ -50,28 +62,6 @@ Please find information on migrating here: If you start from the scratch, ``ng add`` will take care of these settings. -## Upgrade from Version 1.x - -After updating the libs, you need to adjust the ``webpack.conf.js`` a bit: - - -```diff -module.exports = { - output: { - uniqueName: "delme3", -+ publicPath: "auto" - }, - optimization: { - runtimeChunk: false - }, -+ resolve: { -+ alias: { -+ ...sharedMappings.getAliases(), -+ } -+ }, - [...] -} -``` ## Usage ๐ ๏ธ @@ -81,13 +71,23 @@ module.exports = { 2. Adjust the generated ``webpack.config.js`` file 3. Repeat this for further projects in your workspace (if needed) -## Nx +### Nx 1. ``npm install @angular-architects/module-federation`` 2. ``ng g @angular-architects/module-federation:init`` 3. Adjust the generated ``webpack.config.js`` file 4. Repeat this for further projects in your workspace (if needed) +### ๐๐ฅ Version 14+: Use the --type switch to get the new streamlined configuration + +With version 14, we've introduced a --type switch for ``ng add`` and the ``init`` schematic. Set it to one of the following values to get a more streamlined configuration file: + +- ``host`` +- ``dynamic-host`` +- ``remote`` + +A dynamic host reads the micro frontend's URLs from a configuration file at runtime. + ## Getting Started ๐งช Please find here a [tutorial](https://github.com/angular-architects/module-federation-plugin/blob/12.0.0/libs/mf/tutorial/tutorial.md) that shows how to use this plugin. @@ -105,11 +105,8 @@ Please have a look at this [article series about Module Federation](https://www. This [example](https://github.com/manfredsteyer/module-federation-plugin-example) loads a microfrontend into a shell: -![Microfrontend Loaded into Shell](https://github.com/angular-architects/module-federation-plugin/raw/main/packages/mf/tutorial/result.png) - Please have a look into the example's **readme**. It points you to the important aspects of using Module Federation. - ## Advanced Features While the above-mentioned tutorial and blog articles guide you through using Module Federation, this section draws your attention to some advanced aspects of this plugin and Module Federation in general. @@ -190,7 +187,30 @@ Let's assume, you have an Angular CLI Monorepo or an Nx Monorepo using path mapp You can now share such a library across all your micro frontends (apps) in your mono repo. This means, this library will be only loaded once. -To accomplish this, just register this lib name with the ``SharedMappings`` instance in your webpack config: +#### New streamlined configuration in version 14+ + +Beginning with version 14, we use a more steamlined configuration, when using the above mentioned --type switch with one of the following options: ``remote``, ``host``, ``dynamic-host``. + +This new configuration automatically shares all local libararies. Hence, you don't need to do a thing. + +However, if you want to control, which local libraries to share, you can use the the ``sharedMappings`` array: + +```javascript +module.exports = withModuleFederationPlugin({ + + shared: { + ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), + }, + + sharedMappings: ['shared-lib'], +}); +``` + +Please don't forget that sharing in Module Federation is always an opt-in: You need to add this setting to each micro frontend that should share it. + +#### Legacy-Syntax and version 12-13 + +In previous versions, you registered the lib name with the ``SharedMappings`` instance in your webpack config: ```javascript const mf = require("@angular-architects/module-federation/webpack"); @@ -207,7 +227,7 @@ sharedMappings.register( Beginning with version 1.2, the boilerplate for using ``SharedMappings`` is generated for you. You only need to add your lib's name here. -This generated code includes providing the metadata for these libraries for the ``ModuleFederationPlugin`` and adding a plugin making sure that even source code generated by the Angular Compiler uses the shared version of the library. +This generated code includes providing metadata for these libraries for the ``ModuleFederationPlugin`` and adding a plugin making sure that even source code generated by the Angular Compiler uses the shared version of the library. ```javascript plugins: [ @@ -297,6 +317,28 @@ The options passed to shareAll are applied to all dependencies found in your ``p This might come in handy in an mono repo scenario and when doing some experiments/ trouble shooting. +#### Eager and Pinned + +> Big thanks to [Michael Egger-Zickes](https://twitter.com/MikeZks), who came up with these solutions. + +Module Federation allows to directly bundle shared dependencies into your app's bundles. Hence, you don't need to load an additional bundle per shared dependency. This can be interesting to improve an application's startup performance, when there are lots of shared dependencies. + +One possible usage for improving the startup times is to set ``eager`` to ``true`` **just** for the host. The remotes loaded later can reuse these eager dependencies alothough they've been shipped via the host's bundle (e. g. its ``main.js``). This works best, if the host always has the highest compatible versions of the shared dependencies. Also, in this case, you don't need to load the remote entry points upfront. + +While the ``eager`` flag is an out of the box feature provided by module federation since its very first days, we need to adjust the webpack configuration used by the Angular CLI a bit to avoid code duplication in the generated bundles. The new ``withModuleFederationPlugin`` helper that has been introduces with this plugin's version 14 and is the basis for the new streamlined configuration, does this by default. The config just needs to set eager to ``true``. + +```javascript +module.exports = withModuleFederationPlugin({ + + shared: { + ...shareAll({ singleton: true, eager: true, pinned: true, strictVersion: true, requiredVersion: 'auto' }), + }, + +}); +``` + +As shown in the last example, we also added another property: pinned. This makes sure, the shared dependency in put into the application's (e. g. the host's) bundle, even though it's not used there. This allows to preload dependencies that are needed later but subsequently loaded micro frontends via one bundle. + ### Nx Integration If the plugin detects that you are using Nx (it basically looks for a ``nx.json``), it uses the builders provided by Nx. @@ -425,8 +467,6 @@ shared: share({ }) ``` - - #### Not exported Components If you use a shared component without exporting it via your library's barrel (``index.ts`` or ``public-api.ts``), you get the following error at runtime: diff --git a/libs/mf/collection.json b/libs/mf/collection.json index 26fa0f98..0263bc4f 100644 --- a/libs/mf/collection.json +++ b/libs/mf/collection.json @@ -7,7 +7,11 @@ "factory": "./src/schematics/mf/schematic#add", "schema": "./src/schematics/mf/schema.json", "description": "Initialize an angular project for webpack module federation", - "aliases": ["init"] + }, + "init": { + "factory": "./src/schematics/mf/schematic#add", + "schema": "./src/schematics/mf/schema.json", + "description": "Initialize an angular project for webpack module federation", }, "config": { "factory": "./src/schematics/mf/schematic", diff --git a/libs/mf/package.json b/libs/mf/package.json index a8fbdde9..93b3f0f7 100644 --- a/libs/mf/package.json +++ b/libs/mf/package.json @@ -1,6 +1,6 @@ { "name": "@angular-architects/module-federation", - "version": "14.3.0-beta.4", + "version": "14.3.0", "license": "MIT", "repository": { "type": "GitHub", @@ -17,7 +17,7 @@ "schematics": "./collection.json", "builders": "./builders.json", "dependencies": { - "@angular-architects/module-federation-runtime": "14.3.0-beta.4", + "@angular-architects/module-federation-runtime": "14.3.0", "word-wrap": "^1.2.3", "callsite": "^1.0.0", "node-fetch": "^2.6.7", diff --git a/libs/mf/src/schematics/mf/files/webpack.config.js b/libs/mf/src/schematics/mf/files/webpack.config.js index 4651413d..784cadad 100644 --- a/libs/mf/src/schematics/mf/files/webpack.config.js +++ b/libs/mf/src/schematics/mf/files/webpack.config.js @@ -16,5 +16,4 @@ module.exports = withModuleFederationPlugin({ ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), }, - sharedMappings: [], }); diff --git a/libs/mf/src/schematics/mf/schematic.ts b/libs/mf/src/schematics/mf/schematic.ts index 223f6869..0770917d 100644 --- a/libs/mf/src/schematics/mf/schematic.ts +++ b/libs/mf/src/schematics/mf/schematic.ts @@ -301,11 +301,11 @@ export default function config(options: MfSchematicSchema): Rule { const dep = getPackageJsonDependency(tree, "ngx-build-plus"); - if (!dep || !semver.satisfies(dep.version, '>=14.0.0-beta.0')) { + if (!dep || !semver.satisfies(dep.version, '>=14.0.0')) { addPackageJsonDependency(tree, { name: 'ngx-build-plus', type: NodeDependencyType.Dev, - version: '>=14.0.0-beta.0', + version: '^14.0.0', overwrite: true }); diff --git a/libs/mf/src/schematics/migrate-to-14-3/schematic.ts b/libs/mf/src/schematics/migrate-to-14-3/schematic.ts index 683b3502..7796a46f 100644 --- a/libs/mf/src/schematics/migrate-to-14-3/schematic.ts +++ b/libs/mf/src/schematics/migrate-to-14-3/schematic.ts @@ -9,7 +9,7 @@ export function index(): Rule { addPackageJsonDependency(tree, { name: 'ngx-build-plus', type: NodeDependencyType.Dev, - version: '>=14.0.0-beta.0', + version: '^14.0.0', overwrite: true }); diff --git a/libs/mf/tutorial/mfe1.png b/libs/mf/tutorial/mfe1.png index c6a1cac5..05e1a4cb 100644 Binary files a/libs/mf/tutorial/mfe1.png and b/libs/mf/tutorial/mfe1.png differ diff --git a/libs/mf/tutorial/result.png b/libs/mf/tutorial/result.png index fa66ed59..8e9562e2 100644 Binary files a/libs/mf/tutorial/result.png and b/libs/mf/tutorial/result.png differ diff --git a/libs/mf/tutorial/shell.png b/libs/mf/tutorial/shell.png index f0993eba..18fed558 100644 Binary files a/libs/mf/tutorial/shell.png and b/libs/mf/tutorial/shell.png differ diff --git a/libs/mf/tutorial/tutorial.md b/libs/mf/tutorial/tutorial.md index af07651d..70c65ad9 100644 --- a/libs/mf/tutorial/tutorial.md +++ b/libs/mf/tutorial/tutorial.md @@ -6,7 +6,7 @@ This tutorial shows how to use Webpack Module Federation together with the Angul ![Microfrontend Loaded into Shell](https://github.com/angular-architects/module-federation-plugin/raw/main/libs/mf/tutorial/result.png) -**Important**: This tutorial is written for Angular and **Angular CLI 13.1** and higher. To find out about the small differences for lower versions of Angular and for the migration from such a lower version, please have a look to our [migration guide](https://github.com/angular-architects/module-federation-plugin/blob/main/migration-guide.md). +**Important**: This tutorial is written for Angular and **Angular CLI 14** and higher. To find out about the small differences for lower versions of Angular and for the migration from such a lower version, please have a look to our [migration guide](https://github.com/angular-architects/module-federation-plugin/blob/main/migration-guide.md). ## Part 1: Clone and Inspect the Starterkit @@ -27,13 +27,13 @@ In this part you will clone the starterkit and inspect its projects. ``` 3. Start the shell (``ng serve shell -o``) and inspect it a bit: - 1. Click on the ``flights`` link. It leads to a dummy route. This route will later be used for loading the separately compiled microfrontend. + 1. Click on the ``flights`` link. It leads to a dummy route. This route will later be used for loading the separately compiled Micro Frontend. 2. Have a look to the shell's source code. 3. Stop the CLI (``CTRL+C``). -4. Do the same for the microfrontend. In this project, it's called ``mfe1`` (Microfrontend 1) You can start it with ``ng serve mfe1 -o``. +4. Do the same for the Micro Frontend. In this project, it's called ``mfe1`` (Micro Frontend 1) You can start it with ``ng serve mfe1 -o``. ## Part 2: Activate and Configure Module Federation @@ -42,85 +42,58 @@ Now, let's activate and configure module federation: 1. Install ``@angular-architects/module-federation`` into the shell and into the micro frontend: ``` - ng add @angular-architects/module-federation --project shell --port 5000 + ng add @angular-architects/module-federation --project mfe1 --type remote --port 4201 - ng add @angular-architects/module-federation --project mfe1 --port 3000 + ng add @angular-architects/module-federation --project shell --type host --port 4200 ``` This activates module federation, assigns a port for ng serve, and generates the skeleton of a module federation configuration. -2. Open the ``tsconfig.json`` in your workspace's root and ensure your self that the ``target`` property points to ``ES2020`` or higher. This is a prerequisite for using Module Federation with Angular 13.1 or higher. - 3. Switch into the project ``mfe1`` and open the generated configuration file ``projects\mfe1\webpack.config.js``. It contains the module federation configuration for ``mfe1``. Adjust it as follows: ```javascript - const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); + const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack'); - [...] + module.exports = withModuleFederationPlugin({ - module.exports = { - [...], - plugins: [ - new ModuleFederationPlugin({ - - library: { type: "module" }, - - // For remotes (please adjust) - name: "mfe1", - filename: "remoteEntry.js", - exposes: { - // Update this: - './Module': './projects/mfe1/src/app/flights/flights.module.ts', - }, - shared: share({ - "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - [...] - }) - }), - [...] - ], - }; + name: 'mfe1', + + exposes: { + // Update this whole line (both, left and right part): + './Module': './projects/mfe1/src/app/flights/flights.module.ts' + }, + + shared: { + ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), + }, + + }); ``` This exposes the ``FlightsModule`` under the Name ``./Module``. Hence, the shell can use this path to load it. -3. Switch into the ``shell`` project and open the file ``projects\shell\webpack.config.js``. Adjust it as follows: +3. Switch into the ``shell`` project and open the file ``projects\shell\webpack.config.js``. Make sure, the mapping in the remotes section uses port ``4201`` (and hence, points to the Micro Frontend): ```javascript - const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); + const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack'); - [...] + module.exports = withModuleFederationPlugin({ - module.exports = { - [...], - plugins: [ - new ModuleFederationPlugin({ - - library: { type: "module" }, - - // Make sure to use port 3000 - remotes: { - 'mfe1': "http://localhost:3000/remoteEntry.js" - }, - shared: share({ - "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, - [...] - }) - }), - [...] - ], - }; + remotes: { + // Check this line. Is port 4201 configured? + "mfe1": "http://localhost:4201/remoteEntry.js", + }, + + shared: { + ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), + }, + + }); ``` - This references the separately compiled and deployed ``mfe1`` project. There are some alternatives to configure its URL (see links at the end). + This references the separately compiled and deployed ``mfe1`` project. -4. Open the ``shell``'s router config (``projects\shell\src\app\app.routes.ts``) and add a route loading the microfrontend: +4. Open the ``shell``'s router config (``projects\shell\src\app\app.routes.ts``) and add a route loading the Micro Frontend: ```javascript { @@ -150,27 +123,29 @@ Now, let's try it out! **Hint:** You might use two terminals for this. -2. After a browser window with the shell opened (``http://localhost:5000``), click on ``Flights``. This should load the microfrontend into the shell: +2. After a browser window with the shell opened (``http://localhost:4200``), click on ``Flights``. This should load the Micro Frontend into the shell: ![Shell](https://github.com/angular-architects/module-federation-plugin/raw/main/libs/mf/tutorial/shell.png) -3. Also, ensure yourself that the microfrontend also runs in standalone mode at http://localhost:3000: +3. Also, ensure yourself that the Micro Frontend also runs in standalone mode at http://localhost:4201: ![Microfrontend](https://github.com/angular-architects/module-federation-plugin/raw/main/libs/mf/tutorial/mfe1.png) +**Hint:** You can also call the following script to start all projects at once: ``npm run run:all``. This script is added by the Module Federation plugin. Congratulations! You've implemented your first Module Federation project with Angular! ## Part 4: Switch to Dynamic Federation -Now, let's remove the need for registering the micro frontends upfront with with shell. +Now, let's remove the need for registering the Micro Frontends upfront with with shell. + +### Part 4a: Basic Usage of Dynamic Federation -1. Switch to your ``shell`` application and open the file ``webpack.config.js``. Here, remove the registered remotes: +1. Switch to your ``shell`` application and open the file ``projects\shell\webpack.config.js``. Here, remove the registered remotes: ```javascript remotes: { - // Remove this line or comment it out: - // "mfe1": "http://localhost:3000/remoteEntry.js", + // "mfe1": "http://localhost:4201/remoteEntry.js", }, ``` @@ -187,7 +162,7 @@ Now, let's remove the need for registering the micro frontends upfront with with loadChildren: () => loadRemoteModule({ type: 'module', - remoteEntry: 'http://localhost:3000/remoteEntry.js', + remoteEntry: 'http://localhost:4201/remoteEntry.js', exposedModule: './Module' }) .then(m => m.FlightsModule) @@ -196,13 +171,15 @@ Now, let's remove the need for registering the micro frontends upfront with with ] ``` - *Remarks:* ``type: 'module'`` is needed for Angular 13.1 or higher as beginning with version 13 the CLI emits EcmaScript modules instead of "plain old" JavaScript files. + *Remarks:* ``type: 'module'`` is needed for Angular 13 or higher as beginning with version 13 the CLI emits EcmaScript modules instead of "plain old" JavaScript files. 3. Restart both, the ``shell`` and the micro frontend (``mfe1``). 4. The shell should still be able to load the micro frontend. However, now it's loaded dynamically. -This was quite easy, wasn't it? However, we can improve this solution a bit. Ideally, we load the remote entry upfront before Angular bootstraps. In this early phase, Module Federation tries to determine the highest compatible versions of all dependencies. Let's assume, the shell provides version 1.0.0 of a dependency (specifying ^1.0.0 in its ``package.json``) and the micro frontend uses version 1.1.0 (specifying ^1.1.0 in its ``package.json``). In this case, they would go with version 1.1.0. However, this is only possible if the remote's entry is loaded upfront. +### Part 4b: Loading Meta Data Upfront + +This was quite easy, wasn't it? However, we can improve this solution a bit. Ideally, we load the Micro Frontend's remoteEntry.js upfront.before Angular bootstraps. This file contains meta data about the Micro Frontend, esp. about its shared dependencies. Knowing about them upfront help Module Federation to avoid version conflicts. 1. Switch to the ``shell`` project and open the file ``main.ts``. Adjust it as follows: @@ -210,7 +187,10 @@ This was quite easy, wasn't it? However, we can improve this solution a bit. Ide import { loadRemoteEntry } from '@angular-architects/module-federation'; Promise.all([ - loadRemoteEntry({type: 'module', remoteEntry: 'http://localhost:3000/remoteEntry.js') + loadRemoteEntry({ + type: 'module', + remoteEntry: 'http://localhost:4201/remoteEntry.js' + }) ]) .catch(err => console.error('Error loading remote entries', err)) .then(() => import('./bootstrap')) @@ -221,7 +201,54 @@ This was quite easy, wasn't it? However, we can improve this solution a bit. Ide 3. The shell should still be able to load the micro frontend. -## Step 5: Share a Library of Your Monorepo + +### Part 4c: Use a Registry + +So far, we just hardcoded the urls pointing to our Micro Frontends. However, in a real world scenario, we would rather get this information at runtime from a config file or a registry service. This is what this exercise is about. + +1. Switch to the shell, and create a file ``mf.manifest.json`` in its ``assets`` folder (``projects\shell\src\assets\mf.manifest.json``): + + ```json + { + "mfe1": "http://localhost:4201/remoteEntry.js" + } + ``` + +2. Adjust the shell's ``main.ts`` (``projects/shell/src/main.ts``) as follows: + + ```typescript + import { loadManifest } from '@angular-architects/module-federation'; + + loadManifest('assets/mf.manifest.json') + .catch(err => console.error('Error loading remote entries', err)) + .then(() => import('./bootstrap')) + .catch(err => console.error(err)); + ``` + + The imported ``loadManifest`` function also loads the remote entry points. + +3. Adjust the shell's lazy route pointing to the Micro Frontend as follows (``projects/shell/src/app/app.routes.ts``): + + ```typescript + { + path: 'flights', + loadChildren: () => + loadRemoteModule({ + type: 'manifest', + remoteName: 'mfe1', + exposedModule: './Module' + }) + .then(m => m.FlightsModule) + }, + ``` + +4. Restart both, the ``shell`` and the micro frontend (``mfe1``). + +5. The shell should still be able to load the micro frontend. + +**Hint:** The ``ng add`` command used initially also provides an option ``--type dynamic-host``. This makes ng add to generate the ``mf.manifest.json`` and generates the call to ``loadManifest`` in the ``main.ts``. + +## Step 5: Communication Between Micro Frontends and Sharing Monorepo Libraries 1. Add a library to your monorepo: @@ -229,31 +256,21 @@ This was quite easy, wasn't it? However, we can improve this solution a bit. Ide ng g lib auth-lib ``` -2. In your ``tsconfig.json`` in the project's root, adjust the path mapping for ``auth-lib`` so that it points to the libs entry point: +2. In your ``tsconfig.json`` in the workspace's root, adjust the path mapping for ``auth-lib`` so that it points to the libs entry point: ```json "auth-lib": [ - "projects/auth-lib/src/public-api.ts" + "projects/auth-lib/src/public-api.ts" ] ``` 3. As most IDEs only read global configuration files like the ``tsconfig.json`` once, restart your IDE (Alternatively, your IDE might also provide an option for reloading these settings). -4. Open the ``shell``'s ``webpack.config.js`` and register the created ``auth-lib`` with the ``sharedMappings``: +4. Switch to your ``auth-lib`` project and open the file ``auth-lib.service.ts`` (``projects\auth-lib\src\lib\auth-lib.service.ts``). Adjust it as follows: ```typescript - const sharedMappings = new mf.SharedMappings(); - sharedMappings.register( - path.join(__dirname, '../../tsconfig.json'), - ['auth-lib'] // <-- Add this entry! - ); - ``` + import { Injectable } from '@angular/core'; -5. Also open the micro frontends (``mfe1``) ``webpack.config.js`` and do the same. - -6. Switch to your ``auth-lib`` project and open the file ``auth-lib.service.ts``. Adjust it as follows: - - ```typescript @Injectable({ providedIn: 'root' }) @@ -275,7 +292,7 @@ This was quite easy, wasn't it? However, we can improve this solution a bit. Ide } ``` -7. Switch to your ``shell`` project and open its ``app.component.ts``. Use the shared ``AuthLibService`` to login a user: +5. Switch to your ``shell`` project and open its ``app.component.ts`` (``projects\shell\src\app\app.component.ts``). Use the ``AuthLibService`` to login a user: ```typescript import { AuthLibService } from 'auth-lib'; @@ -299,11 +316,11 @@ This was quite easy, wasn't it? However, we can improve this solution a bit. Ide ```typescript export class FlightsSearchComponent { - [...] - + // Add this: user = this.service.user; - constructor(private service: AuthLibService, [...]) { } + // And add that: + constructor(private service: AuthLibService) { } [...] } @@ -313,15 +330,83 @@ This was quite easy, wasn't it? However, we can improve this solution a bit. Ide ```html