{"id":4635,"date":"2020-11-26T00:01:24","date_gmt":"2020-11-25T23:01:24","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=4635"},"modified":"2024-01-19T15:17:42","modified_gmt":"2024-01-19T14:17:42","slug":"using-module-federation-with-monorepos-and-angular","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/","title":{"rendered":"Using Module Federation with (Nx) Monorepos and Angular"},"content":{"rendered":"<div class=\"wp-post-series-box series-module-federation wp-post-series-box--expandable\">\n\t\t\t<input id=\"collapsible-series-module-federation6a0f86df93178\" class=\"wp-post-series-box__toggle_checkbox\" type=\"checkbox\">\n\t\n\t<label\n\t\tclass=\"wp-post-series-box__label\"\n\t\t\t\t\tfor=\"collapsible-series-module-federation6a0f86df93178\"\n\t\t\ttabindex=\"0\"\n\t\t\t\t>\n\t\t<p class=\"wp-post-series-box__name wp-post-series-name\">\n\t\t\tThis is post 6 of 10 in the series <em>&ldquo;Module Federation&rdquo;<\/em>\t\t<\/p>\n\t\t\t<\/label>\n\n\t\t\t<div class=\"wp-post-series-box__posts\">\n\t\t\t<ol>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/the-microfrontend-revolution-module-federation-in-webpack-5\/\">The Microfrontend Revolution: Module Federation in Webpack 5<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/the-microfrontend-revolution-part-2-module-federation-with-angular\/\">The Microfrontend Revolution: Module Federation with Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-module-federation-with-angular\/\">Dynamic Module Federation with Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/dynamic-module-federation-with-angular-2\/\">Building A Plugin-based Workflow Designer With Angular and Module Federation<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/getting-out-of-version-mismatch-hell-with-module-federation\/\">Getting Out of Version-Mismatch-Hell with Module Federation<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><span class=\"wp-post-series-box__current\">Using Module Federation with (Nx) Monorepos and Angular<\/span><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/pitfalls-with-module-federation-and-angular\/\">Pitfalls with Module Federation and Angular<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\">Multi-Framework and -Version Micro Frontends with Module Federation: Your 4 Steps Guide<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/module-federation-with-angulars-standalone-components\/\">Module Federation with Angular&#8217;s Standalone Components<\/a><\/li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-architects-module-federation-14-3\/\">What&#8217;s New in our Module Federation Plugin 14.3?<\/a><\/li>\n\t\t\t\t\t\t\t<\/ol>\n\t\t<\/div>\n\t<\/div>\n<h1>Using Module Federation with Nx Monorepos and Angular<\/h1>\n<p>While it sounds like a contradiction, the combination of Micro Frontends and Monorepos can actually be quite tempting: No <strong>version conflicts<\/strong> by design, easy code sharing and <strong>optimized bundles<\/strong> are some of the benefits you get. Also, you can still <strong>deploy<\/strong> Micro Frontends <strong>separately<\/strong> and <strong>isolate<\/strong> them from each other. <\/p>\n<\/p>\n<p>This article <strong>compares the consequences<\/strong> of using <strong>several repositories<\/strong> (&quot;Micro Frontends by the book&quot;) and one sole <strong>monorepo<\/strong>. After that, it shows with an example, how to use Module Federation in an Nx monorepo.<\/p>\n<p>If you want to have a look at the \ud83d\udcc2 <a href=\"https:\/\/github.com\/manfredsteyer\/nx-module-federation-demo\">source code<\/a> used here, you can check out <a href=\"https:\/\/github.com\/manfredsteyer\/nx-module-federation-demo\">this repository<\/a>. <\/p>\n<blockquote>\n<p>Big thanks to the awesome <a href=\"https:\/\/twitter.com\/wSokra\">Tobias Koppers<\/a> who gave me valuable insights into this topic and to the one and only <a href=\"https:\/\/twitter.com\/valorkin\">Dmitriy Shekhovtsov<\/a> who helped me using the Angular CLI\/webpack 5 integration for this.<\/p>\n<\/blockquote>\n<p><strong>Important<\/strong>: This article is written for <strong>Angular 14.x<\/strong> and higher. Hence, you also need <strong>Nx 14.2.x<\/strong> or 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 <a href=\"https:\/\/github.com\/angular-architects\/module-federation-plugin\/blob\/main\/migration-guide.md\">migration guide<\/a>.<\/p>\n<h2>Multiple Repos vs. Monorepos<\/h2>\n<p>I know, the discussion about using multiple repos vs. monorepos can be quite emotional. Different people made different experiences with both approaches. However, I can tell you: I've seen both working in huge real-world projects. Still, both comes <strong>with different consequences<\/strong>, I'm going to discuss in the following two section. <\/p>\n<p>At the end of the day, you need to <strong>evaluate<\/strong> these consequences against your very project situation and <strong>goals<\/strong>. This is what software architecture is about.<\/p>\n<h2>Multiple Repositories: Micro Frontends by the Book<\/h2>\n<p>A traditional approach uses a separate repository per Micro Frontend:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/multi.png\" alt=\"One Repository per Micro Frontend\" \/><\/p>\n<p>This is also a quite usual for Micro Services and it provides the following <strong>advantages<\/strong>:<\/p>\n<ul>\n<li>\n<p>Micro Frontends -- and hence the individual business domains -- are isolated from each other. As there are no dependencies between them, different teams can evolve them separately.<\/p>\n<\/li>\n<li>\n<p>Each team can concentrate on their Micro Frontend. They only need to focus on their very own repository. <\/p>\n<\/li>\n<li>\n<p>Each team has the maximum amount of freedom in their repository. They can go with their very own architectural decisions, tech stacks, and build processes. Also, they decide by themselves when to update to newer versions.<\/p>\n<\/li>\n<li>\n<p>Each Micro Frontend can be separately deployed.<\/p>\n<\/li>\n<\/ul>\n<p>As this best fits the original ideas of Micro Frontends, I call this approach &quot;Micro Frontends by the book&quot;. However, there are also some <strong>disadvantages<\/strong>:<\/p>\n<ul>\n<li>\n<p>We need to version and distribute shared dependencies via npm. This can become quite an overhead, as after every change we need to assign a new version, publish it, and install it into the respective Micro Frontends. <\/p>\n<\/li>\n<li>\n<p>As each team can use its own tech stack, we can end up with different frameworks and different versions of them. This might lead to version conflicts in the browser and to increased bundle sizes. <\/p>\n<\/li>\n<\/ul>\n<p>Of course, there are approaches to <strong>compensate for these drawbacks<\/strong>: For instance, we can automate the distribution of shared libraries to minimize the overhead. Also, we can avoid version conflicts by not sharing libraries between different Micro Frontends. Wrapping these Micro Frontends into web components further abstracts away the differences between frameworks. <\/p>\n<p>While this prevents version conflicts, we still have increased bundle sizes. Also, we might need some workarounds here or there as Angular is not designed to work with another version of itself in the same browser window. Needless to say that there is no support by the Angular team for this idea.<\/p>\n<p>If you find out that the advantages of this approach outweigh the disadvantages, you find a solution for <a href=\"https:\/\/www.angulararchitects.io\/aktuelles\/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide\/\">mixing and matching different frameworks and versions here<\/a>.<\/p>\n<p>However, if you feel that the disadvantages weigh heavier, the next sections show an alternative.<\/p>\n<h2>Micro Frontends with Monorepos<\/h2>\n<p>Nearly all of the disadvantages outlined above can be prevented by putting all Micro Frontends into one sole monorepo:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/mono.png\" alt=\"Micro Frontends in a monorepo\" \/><\/p>\n<p>Now, sharing libraries is easy and there is only one version of everything, hence we don't end up with version conflicts in the browser. We can also <strong>keep some advantages outlined above<\/strong>:<\/p>\n<ul>\n<li>\n<p>Micro Frontends can be <strong>isolated<\/strong> from each other by using <strong>linting<\/strong> rules. They prevent one Micro Frontend from depending upon others. Hence, teams can separately evolve their Micro Frontend.<\/p>\n<\/li>\n<li>\n<p>Micro Frontends can still be <strong>separately deployed.<\/strong> <\/p>\n<\/li>\n<\/ul>\n<p>Now, the question is, where's the catch? Well, the thing is, now we are <strong>giving up<\/strong> some of the <strong>freedom<\/strong>: Teams need to agree on <strong>one version<\/strong> of dependencies like Angular and on a common update cycle for them. To put it in another way: We trade in some freedom to prevent version conflicts and increased bundle sizes.<\/p>\n<p>One more time, you need to evaluate all these consequences for your very project. Hence, you need to know your architecture goals and prioritize them. As mentioned, I've seen both working in the wild in several projects. It's all about the different consequences.<\/p>\n<h2>Monorepo Example<\/h2>\n<p>After discussing the consequences of the approach outlined here, let's have a look at an implementation. The example used here is a Nx monorepo with a Micro Frontend shell (<code>shell<\/code>) and a Micro Frontend (<code>mfe1<\/code>, &quot;micro frontend 1&quot;). Both share a common library for authentication (<code>auth-lib<\/code>) that is also located in the monorepo. Also, <code>mfe1<\/code> uses a library <code>mfe1-domain-logic<\/code>.<\/p>\n<p>If you haven't used Nx before, just assume a CLI workspace with tons additional features. You can find more <a href=\"https:\/\/www.angulararchitects.io\/aktuelles\/tutorial-first-steps-with-nx-and-angular-architecture\/\">infos on Nx in our tutorial<\/a>.<\/p>\n<p>To visualize the monorepo's structure, one can use the Nx CLI to request a dependency graph:<\/p>\n<pre><code class=\"language-bash\">nx graph<\/code><\/pre>\n<p>If you don't have installed this CLI, you can easily get it via npm (<code>npm i -g nx<\/code>). The displayed graph looks like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/graph.png\" alt=\"Dependency Graph generated by Nx\" \/><\/p>\n<p>The <code>auth-lib<\/code> provides two components. One is logging-in users and the other one displays the current user. They are used by both, the <code>shell<\/code> and <code>mfe1<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/11\/schema.png\" alt=\"Schema\" \/><\/p>\n<p>Also, the <code>auth-lib<\/code> stores the current user's name in a service.<\/p>\n<p>As usual in Nx and Angular monorepos, libraries are referenced with path mappings defined in <code>tsconfig.base.json<\/code> (Nx)  or <code>tsconfig.json<\/code> (Angular CLI):<\/p>\n<pre><code class=\"language-json\"> &quot;paths&quot;: {\n     &quot;@demo\/auth-lib&quot;: [\n         &quot;libs\/auth-lib\/src\/index.ts&quot;\n     ]\n },<\/code><\/pre>\n<p>The <code>shell<\/code> and <code>mfe1<\/code> (as well as further Micro Frontends we might add in the future) need to be deployable in separation and loaded at runtime. <\/p>\n<p>However, we don't want to load the <code>auth-lib<\/code> twice or several times! Archiving this with an npm package is not that difficult. This is one of the most obvious and easy to use features of Module Federation. The next sections discuss how to do the same with libraries of a monorepo.<\/p>\n<h2>The Shared Lib<\/h2>\n<p>Before we delve into the solution, let's have a look at the <code>auth-lib<\/code>. It contains an <code>AuthService<\/code> that logs-in the user and remembers them using the property <code>_userName<\/code>:<\/p>\n<pre><code class=\"language-typescript\"> @Injectable({\n   providedIn: &#039;root&#039;\n })\n export class AuthService {\n\n   \/\/ tslint:disable-next-line: variable-name\n   private _userName: string = null;\n\n   public get userName(): string {\n     return this._userName;\n   }\n\n   constructor() { }\n\n   login(userName: string, password: string): void {\n     \/\/ Authentication for honest users\n     \/\/ (c) Manfred Steyer\n     this._userName = userName;\n   }\n\n   logout(): void {\n     this._userName = null;\n   }\n }<\/code><\/pre>\n<p>Besides this service, there is also a <code>AuthComponent<\/code> with the UI for logging-in the user and a <code>UserComponent<\/code> displaying the current user's name. Both components are registered with the library's NgModule:<\/p>\n<pre><code class=\"language-typescript\"> @NgModule({\n   imports: [\n     CommonModule,\n     FormsModule\n   ],\n   declarations: [\n     AuthComponent,\n     UserComponent\n   ],\n   exports: [\n     AuthComponent,\n     UserComponent\n   ],\n })\n export class AuthLibModule {}<\/code><\/pre>\n<p>As every library, it also has a barrel <code>index.ts<\/code> (sometimes also called <code>public-api.ts<\/code>) serving as the entry point. It exports everything consumers can use:<\/p>\n<pre><code class=\"language-typescript\"> export * from &#039;.\/lib\/auth-lib.module&#039;;\n export * from &#039;.\/lib\/auth.service&#039;;\n\n \/\/ Don&#039;t forget about your components!\n export * from &#039;.\/lib\/auth\/auth.component&#039;;\n export * from &#039;.\/lib\/user\/user.component&#039;;<\/code><\/pre>\n<p><strong>Please note<\/strong> that <code>index.ts<\/code> is also exporting the two components although they are already registered with the also exported <code>AuthLibModule<\/code>. In the scenario discussed here, this is vital in order to make sure it's detected and compiled by Ivy. <\/p>\n<p>Let's assume the shell is using the <code>AuthComponent<\/code> and <code>mfe1<\/code> uses the <code>UserComponent<\/code>. As our goal is to only load the <code>auth-lib<\/code> once, this also allows for sharing information on the logged-in user. <\/p>\n<h2>The Module Federation Configuration<\/h2>\n<p>As in the previous article, we are using the @angular-architects\/module-federation plugin to enable Module Federation for the <code>shell<\/code> and <code>mfe1<\/code>. For this, just run the following commands:<\/p>\n<pre><code class=\"language-javascript\">npm i @angular-architects\/module-federation -D\n\nnpm g @angular-architects\/module-federation:init --project shell --port 4200 --type host\n\nnpm g @angular-architects\/module-federation:init --project mfe1 --port 4201 --type remote<\/code><\/pre>\n<blockquote>\n<p>Meanwhile, Nx also ships with its own <a href=\"https:\/\/nx.dev\/module-federation\/micro-frontend-architecture\">support for Module Federation<\/a>. Beyond the covers, it handles Module Federation in a very similar way as the plugin used here.<\/p>\n<\/blockquote>\n<p>This generates a webpack config for Module Federation. Since version 14.3, the <code>withModuleFederationPlugin<\/code> provides a property <code>sharedMappings<\/code>. Here, we can register the monorepo internal libs we want to share at runtime:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ apps\/shell\/webpack.config.js\n\nconst { shareAll, withModuleFederationPlugin } = require(&#039;@angular-architects\/module-federation\/webpack&#039;);\n\nmodule.exports = withModuleFederationPlugin({\n\n     remotes: {\n         &#039;mfe1&#039;: &quot;http:\/\/localhost:4201\/remoteEntry.js&quot; \n     },\n\n     shared: shareAll({ singleton: true, strictVersion: true, requiredVersion: &#039;auto&#039; }),\n\n     sharedMappings: [&#039;@demo\/auth-lib&#039;],\n\n });<\/code><\/pre>\n<p>As sharing is always an opt-in in Module Federation, we also need the same setting in the Micro Frontend's configuration:<\/p>\n<pre><code class=\"language-typescript\"> \/\/ apps\/mfe1\/webpack.config.js\n\n const { shareAll, withModuleFederationPlugin } = require(&#039;@angular-architects\/module-federation\/webpack&#039;);\n\n module.exports = withModuleFederationPlugin({\n\n     name: &quot;mfe1&quot;,\n\n     exposes: {\n       &#039;.\/Module&#039;: &#039;.\/apps\/mfe1\/src\/app\/flights\/flights.module.ts&#039;,\n     }, \n\n     shared: shareAll({ singleton: true, strictVersion: true, requiredVersion: &#039;auto&#039; }),\n\n     sharedMappings: [&#039;@demo\/auth-lib&#039;],\n\n });<\/code><\/pre>\n<blockquote>\n<p>Since version 14.3, the Module Federation plugin shares all libraries in the monorepo by default. To get this default behavior, just skip the <code>sharedMappings<\/code> property. If you use it, only the mentioned libs are shared.<\/p>\n<\/blockquote>\n<h2>Trying it out<\/h2>\n<p>To try this out, just start the two applications. As we use Nx, this can be done with the following command:<\/p>\n<pre><code class=\"language-javascript\">nx run-many --target serve --all<\/code><\/pre>\n<p>The switch <code>--all<\/code> starts all applications in the monorepo. Instead, you can also go with the switch <code>--projects<\/code> to just start a subset of them:<\/p>\n<pre><code class=\"language-bash\">nx run-many --target serve --projects shell,mfe1<\/code><\/pre>\n<blockquote>\n<p><code>--project<\/code> takes a comma-separated list of project names. Spaces are <strong>not<\/strong> allowed.<\/p>\n<\/blockquote>\n<p>After starting the applications, log-in in the shell and make it to load <code>mfe1<\/code>. If you see the logged-in user name in <code>mfe1<\/code>, you have the proof that <code>auth-lib<\/code> is only loaded once and shared across the applications.<\/p>\n<h2>Isolating Micro Frontends<\/h2>\n<p>One important goal of a Micro Frontend architecture is to isolate Micro Frontends from each other. Only if they don't depend on each other, they can be evolved by autarkic teams. For this, Nx provides <strong>linting<\/strong> rules. Once in place, they give us errors when we directly reference code belonging to another Micro Frontend and hence another business domain.<\/p>\n<p>In the following example, the shell tries to access a library belonging to <code>mfe1<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/linting.png\" alt=\"Linting prevents coupling between Micro Frontends\" \/><\/p>\n<p>To make these error messages appear in your IDE, you need <strong>eslint<\/strong> support. For Visual Studio Code, this can be installed via an extension.<\/p>\n<p>Besides checking against linting rules in your IDE, one can also call the linter on the command line:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/linting-shell.png\" alt=\"Linting on the command line\" \/><\/p>\n<p>The good message: If it works on the command line, it can be automated. For instance, your <strong>build process<\/strong> could execute this command and <strong>prevent merging<\/strong> a feature into the main branch if these linting rules fail: No broken windows anymore.<\/p>\n<p>For configuring these linting rules, we need to <strong>add tags<\/strong> to each app and lib in our monorepo. For this, you can adjust the <code>project.json<\/code> in the app's or lib's folder. For instance, the <code>project.json<\/code> for the shell can be found here: <code>apps\/shell\/project.json<\/code>. At the end, you find a property tag, I've set to <code>scope:shell<\/code>:<\/p>\n<pre><code class=\"language-json\"> {\n     [...]\n     &quot;tags&quot;: [&quot;scope:shell&quot;]\n }<\/code><\/pre>\n<p>The value for the tags are just strings. Hence, you can set any possible value. I've repeated this for <code>mfe1<\/code> (<code>scope:mfe1<\/code>) and the <code>auth-lib<\/code> (<code>scope:auth-lib<\/code>).<\/p>\n<p>Once the tags are in place, you can use them to define <strong>constraints<\/strong> in your <strong>global eslint<\/strong> configuration (<code>.eslintrc.json<\/code>): <\/p>\n<pre><code class=\"language-json\"> &quot;@nrwl\/nx\/enforce-module-boundaries&quot;: [\n   &quot;error&quot;,\n   {\n     &quot;enforceBuildableLibDependency&quot;: true,\n     &quot;allow&quot;: [],\n     &quot;depConstraints&quot;: [\n       {\n         &quot;sourceTag&quot;: &quot;scope:shell&quot;,\n         &quot;onlyDependOnLibsWithTags&quot;: [&quot;scope:shell&quot;, &quot;scope:shared&quot;]\n       },\n       {\n         &quot;sourceTag&quot;: &quot;scope:mfe1&quot;,\n         &quot;onlyDependOnLibsWithTags&quot;: [&quot;scope:mfe1&quot;, &quot;scope:shared&quot;]\n       },\n       {\n         &quot;sourceTag&quot;: &quot;scope:shared&quot;,\n         &quot;onlyDependOnLibsWithTags&quot;: [&quot;scope:shared&quot;]\n       }\n     ]\n   }\n ]<\/code><\/pre>\n<p>After changing global configuration files like the <code>.eslintrc.json<\/code>, it's a good idea to restart your IDE (or at least affected services of your IDE). This makes sure the changes are respected.<\/p>\n<p>More on these ideas and their implementation with Nx can be found in my blog series on <a href=\"https:\/\/www.angulararchitects.io\/aktuelles\/sustainable-angular-architectures-1\/\">Strategic Design (Domain-driven Design) and Angular<\/a>.<\/p>\n<h2>Incremental Builds<\/h2>\n<p>To build all apps, you can use Nx' <code>run-many<\/code> command:<\/p>\n<pre><code class=\"language-bash\">nx run-many --target build --all<\/code><\/pre>\n<p>However, this does not mean that Nx always rebuilds all the Micro Frontends as well as the shell. Instead, it <strong>only rebuilds<\/strong> the <strong>changed<\/strong> apps. For instance, in the following case mfe1 was not changed. Hence, only the shell is rebuilt:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/incremental.png\" alt=\"Nx only rebuilds changed apps\" \/><\/p>\n<blockquote>\n<p>Using the build cache to only recompile changed apps can <strong>dramatically speed up your build times.<\/strong><\/p>\n<\/blockquote>\n<p>This also works for <strong>testing, e2e-tests, and linting<\/strong> out of the box. If an application (or library) hasn't been changed, it's neither retested nor relinted. Instead, the result is taken from the Nx <strong>build cache<\/strong>.<\/p>\n<p>By default, the build cache is located in <code>node_modules\/.cache\/nx<\/code>. However, there are several options for configuring how and where to cache. <\/p>\n<h2>Deploying<\/h2>\n<p>As normally, libraries don't have versions in a monorepo, we should always redeploy all the changed Micro Frontends together. Fortunately, Nx helps with finding out which applications\/ Micro Frontends have been changed or <strong>affected by a change<\/strong>:<\/p>\n<pre><code class=\"language-javascript\">nx print-affected --type app --select projects<\/code><\/pre>\n<p>You might also want to detect the changed applications as part of your <strong>build process<\/strong>. <\/p>\n<blockquote>\n<p>Redeploying all applications that have been changed or affected by a (lib) change is vital, if you share libraries at runtime. If you have a <strong>release branch<\/strong>, it's enough to just redeploy all apps that have been changed in this branch. <\/p>\n<\/blockquote>\n<p>If you want to have a <strong>graphical<\/strong> representation of the changed parts of your monorepo, you can request a dependency graph with the following command:<\/p>\n<pre><code class=\"language-bash\">nx affected:graph<\/code><\/pre>\n<p>Assuming we changed the <code>domain-logic<\/code> lib used by <code>mfe1<\/code>, the result would look as follows:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2022\/06\/affected-dep-graph.png\" alt=\"Dependency graph shows affected projects\" \/><\/p>\n<p>By default, the shown commands <strong>compare<\/strong> your current working directory with the <strong>main branch<\/strong>. However, you can use these commands with the switches <code>--base<\/code> and <code>--head<\/code>.<\/p>\n<pre><code class=\"language-bash\">nx print-affected --type app --select projects --base branch-or-commit-a --head branch-or-commit-b<\/code><\/pre>\n<p>These switches take a <strong>commit hash<\/strong> or the name of a <strong>branch<\/strong>. In the latter case, the last commit of the mentioned branch is used for the comparison.<\/p>\n<h2>What's next? More on Architecture!<\/h2>\n<p>So far, we've seen that Module Federation is a straightforward solution for creating Micro Frontends on top of Angular. However, when dealing with it, several additional questions come in mind:<\/p>\n<ul>\n<li>According to which criteria can we sub-divide a huge application into micro frontends?<\/li>\n<li>Which access restrictions make sense?<\/li>\n<li>Which proven patterns should we use?<\/li>\n<li>How can we avoid pitfalls when working with Module Federation?<\/li>\n<li>Which advanced scenarios are possible?<\/li>\n<\/ul>\n<p>Our free eBook (about 100 pages) covers all these questions and more:<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/book\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/12\/cover-small.png\" alt=\"free ebook\"><\/a><\/p>\n<p>Feel free to <a href=\"https:\/\/www.angulararchitects.io\/book\">download it here<\/a> now!<\/p>\n<h2>Conclusion<\/h2>\n<p>By using monorepos for Micro Frontends you trade in some freedom for preventing issues. You can still deploy Micro Frontends separately and thanks to linting rules provided by Nx Micro Frontends can be isolated from each other. <\/p>\n<p>However, you need to agree on common versions for the frameworks and libraries used. Therefore, you don't end up with version conflicts at runtime. This also prevents increased bundles. <\/p>\n<p>Both works, however, both has different consequences. It's on you to evaluate these consequences for your very project.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The combination of Micro Frontends and monorepos can be quite tempting: Sharing libraries is easy while we can isolate domains using access restrictions and deploy them separately.<\/p>\n","protected":false},"author":9,"featured_media":4640,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[18],"tags":[],"class_list":["post-4635","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","post_series-module-federation"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Using Module Federation with (Nx) Monorepos and Angular - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Module Federation with (Nx) Monorepos and Angular - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"The combination of Micro Frontends and monorepos can be quite tempting: Sharing libraries is easy while we can isolate domains using access restrictions and deploy them separately.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2020-11-25T23:01:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-01-19T14:17:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/11\/title-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1075\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Using Module Federation with (Nx) Monorepos and Angular\",\"datePublished\":\"2020-11-25T23:01:24+00:00\",\"dateModified\":\"2024-01-19T14:17:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/\"},\"wordCount\":2278,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage\"},\"thumbnailUrl\":\"\",\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/\",\"name\":\"Using Module Federation with (Nx) Monorepos and Angular - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage\"},\"thumbnailUrl\":\"\",\"datePublished\":\"2020-11-25T23:01:24+00:00\",\"dateModified\":\"2024-01-19T14:17:42+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage\",\"url\":\"\",\"contentUrl\":\"\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Module Federation with (Nx) Monorepos and Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using Module Federation with (Nx) Monorepos and Angular - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/","og_locale":"en_US","og_type":"article","og_title":"Using Module Federation with (Nx) Monorepos and Angular - ANGULARarchitects","og_description":"The combination of Micro Frontends and monorepos can be quite tempting: Sharing libraries is easy while we can isolate domains using access restrictions and deploy them separately.","og_url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/","og_site_name":"ANGULARarchitects","article_published_time":"2020-11-25T23:01:24+00:00","article_modified_time":"2024-01-19T14:17:42+00:00","og_image":[{"width":1075,"height":720,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2020\/11\/title-1.png","type":"image\/png"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Using Module Federation with (Nx) Monorepos and Angular","datePublished":"2020-11-25T23:01:24+00:00","dateModified":"2024-01-19T14:17:42+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/"},"wordCount":2278,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage"},"thumbnailUrl":"","inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/using-module-federation-with-monorepos-and-angular\/","url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/","name":"Using Module Federation with (Nx) Monorepos and Angular - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage"},"thumbnailUrl":"","datePublished":"2020-11-25T23:01:24+00:00","dateModified":"2024-01-19T14:17:42+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#primaryimage","url":"","contentUrl":""},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/using-module-federation-with-monorepos-and-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Using Module Federation with (Nx) Monorepos and Angular"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/4635","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=4635"}],"version-history":[{"count":4,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/4635\/revisions"}],"predecessor-version":[{"id":24249,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/4635\/revisions\/24249"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=4635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=4635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=4635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}