{"id":27448,"date":"2025-01-02T22:04:26","date_gmt":"2025-01-02T21:04:26","guid":{"rendered":"https:\/\/www.angulararchitects.io\/blog\/nx-with-rspack-and-module-federation\/"},"modified":"2025-01-03T15:04:56","modified_gmt":"2025-01-03T14:04:56","slug":"nx-with-rspack-and-module-federation","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/","title":{"rendered":"Nx and Angular with Rspack and Module Federation"},"content":{"rendered":"<p>In just a few years, <a href=\"https:\/\/module-federation.io\/\">Module Federation<\/a> grew from a first implementation that shipped with webpack 5 to a whole ecosystem. Meanwhile, we have an implementation for <a href=\"https:\/\/rspack.dev\/\">rspack<\/a>, a port to <a href=\"https:\/\/www.npmjs.com\/package\/@module-federation\/vite\">vite<\/a>, and a runtime that can be used across the whole ecosystem. <\/p>\n<p>There are also several third parties in this space: <a href=\"https:\/\/www.zephyr-cloud.io\/\">Zephyr<\/a> offers a cloud-based service for fast deployments leveraging Module Federation, and <a href=\"https:\/\/nx.dev\/\">Nx<\/a> provides a comfortable integration that simplifies building Micro Frontends with Angular, React, and other frameworks and improves incremental builds. Furthermore, there is our take, <a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/micro-frontends-with-modern-angular-part-1-standalone-and-esbuild\/\">Native Federation<\/a>, a portable bundler-agnostic implementation that leverages web standards and integrates into Angular by wrapping the CLI's new esbuild-based <code>ApplicationBuilder.<\/code><\/p>\n<p>Since version 20, Nx offers executors integrating rspack and <a href=\"https:\/\/rsbuild.dev\/\">rsbuild<\/a>. The latter one builds on top of rspack and provides a performant out-of-the-box setup for usual build requirements. Nx' investment into rspack and rsbuild makes incorporating Module Federation on top of rspack easy. While, so far, Nx does not include an official rspack-based executor for Angular projects, <a href=\"https:\/\/x.com\/FerryColum\">Colum Ferry<\/a> from the Nx team recently published an early version of the open-source package <a href=\"https:\/\/www.npmjs.com\/package\/@ng-rsbuild\/plugin-nx\">@ng-rsbuild\/plugin-nx<\/a> that fills this gap by leveraging rsbuild. Also, it already supports SSR.<\/p>\n<p>As a community solution, @ng-rsbuild\/plugin-nx is not an official part of Nx; however, having someone like Colum behind it immediately builds trust.<\/p>\n<p>In this article, I show how to use this package together with Nx, Angular, and Module Federation to build a Micro Frontend-based solution. For this, I'm using my usual Micro Frontend showcase:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/rsbuild-nx-mf.png\" alt=\"Demo Application\" \/><\/p>\n<p>\ud83d\udcc2 <a href=\"https:\/\/github.com\/manfredsteyer\/nx-rspack-mf-demo.git\">Source Code<\/a><\/p>\n<blockquote><p>\nDisclaimer: @ng-rsbuild\/plugin-nx is currently in Alpha. So things might change and be improved. I will keep you posted here.\n<\/p><\/blockquote>\n<h2>Setting up an Nx Workspace<\/h2>\n<p>To get started, let's add the rsbuild plugin for Angular to a newly created Nx 19 workspace and generate a <code>shell<\/code> and a Micro Frontend <code>mfe1<\/code> with it:<\/p>\n<pre><code class=\"language-bash\">npx nx add @ng-rsbuild\/plugin-nx\n\nnpx nx g @ng-rsbuild\/plugin-nx:application shell\nnpx nx g @ng-rsbuild\/plugin-nx:application mfe1<\/code><\/pre>\n<p>For leveraging dynamic Federation, we also need the package @module-federation\/enhanced that contains the Module Federation runtime:<\/p>\n<pre><code class=\"language-bash\">npm i @module-federation\/enhanced<\/code><\/pre>\n<h2>Implementing the Micro Frontend<\/h2>\n<p>The Micro Frontend's <code>AppComponent<\/code> gets a simple implementation:<\/p>\n<pre><code class=\"language-typescript\">@Component({\n  imports: [],\n  selector: &#039;app-root&#039;,\n  templateUrl: &#039;.\/app.component.html&#039;,\n  styleUrl: &#039;.\/app.component.css&#039;,\n})\nexport class AppComponent {\n  title = &#039;myapp&#039;;\n\n  search(): void {\n    alert(&#039;Not implemented!&#039;);\n  }\n}\n\n\/\/ Add default export:\nexport default AppComponent;<\/code><\/pre>\n<p>Please see this simple component as a replacement for a more complex Micro Frontend that might combine several use cases via routing. Please note that the example also defines a <strong>default export<\/strong> for the <code>AppComponent.<\/code> This simplifies lazy loading it into the shell a bit. <\/p>\n<p>For the sake of completeness, you find the component's markup below:<\/p>\n<pre><code class=\"language-html\">&lt;div id=&quot;container&quot;&gt;\n    &lt;h1&gt;Select a Flight&lt;\/h1&gt;\n    &lt;div&gt;\n        &lt;input type=&quot;text&quot; placeholder=&quot;From&quot;&gt;\n    &lt;\/div&gt;\n    &lt;div&gt;\n        &lt;input type=&quot;text&quot; placeholder=&quot;To&quot;&gt;\n    &lt;\/div&gt;\n    &lt;div&gt;\n        &lt;button (click)=&quot;search()&quot;&gt;Search&lt;\/button&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<h2>Async Bootstrapping<\/h2>\n<p>For our Module Federation setup, we need to switch to asynchronous bootstrapping. For this, copy the content of the file <code>mfe1\/src\/main.ts<\/code> to a new file <code>mfe1\/src\/bootstrap.ts<\/code> that is just imported in the former one:<\/p>\n<pre><code class=\"language-typescript\">\/\/ mfe1\/src\/main.ts\nimport(&#039;.\/bootstrap&#039;);<\/code><\/pre>\n<p>It's important to use a dynamic and hence async <code>import<\/code> here. This allows Module Federation to initialize and to take care of loading shared packages in all remaining parts of the application.<\/p>\n<h2>More on this: Angular Architecture Workshop (online, interactive, advanced)<\/h2>\n<p>Become an expert for enterprise-scale and maintainable Angular applications with our <a href=\"https:\/\/www.angulararchitects.io\/en\/angular-workshops\/advanced-angular-enterprise-architecture-incl-ivy\/\">Angular Architecture workshop!<\/a><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/sujet-en.jpg\" alt=\"\" \/><\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/angular-workshops\/advanced-angular-enterprise-architecture-incl-ivy\/\">English Version<\/a> | <a href=\"https:\/\/www.angulararchitects.io\/schulungen\/advanced-angular-enterprise-anwendungen-und-architektur\/\">German Version<\/a><br \/>\n<\/p>\n<h2>Configuring the Micro Frontend<\/h2>\n<p>For configuring Module Federation, we need to adjust the rsbuild configuration, @ng-rsbuild\/plugin-nx generated in <code>mfe1\/rsbuild.config.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import { createConfig } from &#039;@ng-rsbuild\/plugin-angular&#039;;\n\n\/\/ eslint-disable-next-line @nx\/enforce-module-boundaries\nimport { shareAll } from &#039;..\/mf.tools&#039;;\n\nexport default createConfig({\n  browser: &#039;.\/src\/main.ts&#039;,\n}, {\n  server: {\n    port: 4201\n  },\n  tools: {\n    rspack: {\n      output: {\n        uniqueName: &#039;mfe1&#039;,\n        publicPath: &#039;auto&#039;,\n      },\n    },\n  },  \n  moduleFederation: {\n    options: {\n      name: &#039;mfe1&#039;,\n      filename: &#039;remoteEntry.js&#039;,\n      exposes: {\n        &#039;.\/Component&#039;: &#039;.\/src\/app\/app.component.ts&#039;\n      },\n      shared: {\n        ...shareAll({\n          singleton: true,\n          strictVersion: true,\n        })\n      }\n    }\n  }\n});<\/code><\/pre>\n<p>Besides switching to the port 4201 we need to define a <code>publicPath<\/code>. This is the URL the Micro Frontend's bundles are deployed to. The value <code>auto<\/code> defines that at runtime this URL should be inferred. If you want to control the logic for inferring this URL, you can set the <a href=\"https:\/\/module-federation.io\/configure\/getpublicpath.html\">getPublicPath <\/a> property to some JavaScript code executed at runtime.<\/p>\n<p>The remaining configuration consists of a typical Module Federation settings:<\/p>\n<ul>\n<li>The Micro Frontend gets the unique name <code>mfe1<\/code>.<\/li>\n<li>Module Federation is told to put the meta data generated during the build into the file <code>remoteEntry.js<\/code>.<\/li>\n<li>The <code>AppComponent<\/code> is exposed under the name <code>.\/Component<\/code>. Using this name, the shell can import it at runtime.<\/li>\n<li>The Micro Frontend shares all dependencies with other Micro Frontends and the shell at runtime.<\/li>\n<\/ul>\n<p>The used <code>shareAll<\/code> helper simplifies the configuration. Normally, we needed an exhaustive list with all packages to share:<\/p>\n<pre><code class=\"language-typescript\">shared: {\n  &#039;@angular\/animations&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/common&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/compiler&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/core&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/forms&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/platform-browser&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/platform-browser-dynamic&#039;: { singleton: true, strictVersion: true },\n  &#039;@angular\/router&#039;: { singleton: true, strictVersion: true },\n  &#039;@module-federation\/enhanced&#039;: { singleton: true, strictVersion: true },\n  &#039;rxjs&#039;: { singleton: true, strictVersion: true }\n}<\/code><\/pre>\n<p>Setting <code>singleton<\/code> and <code>strictVersion<\/code> to <code>true<\/code> ensures that only one version of each dependency can be loaded at runtime. If several non-compatible versions of the same dependency are present, an Exception is thrown on startup. If we set <code>strictVersion<\/code> to <code>false<\/code> or leave it off, just a warning is written to the JavaScript console.<\/p>\n<p>To avoid writing this exhaustive list by hand, the helper function <a href=\"https:\/\/github.com\/manfredsteyer\/nx-rspack-mf-demo\/blob\/main\/mf.tools.ts\">shareAll<\/a> creates such an entry for all packages found in the project's <code>package.json<\/code> in the node <code>dependencies.<\/code> The simple implementation used here does not add secondary entry points such as @angular\/common\/http. They need to be added by hand. I assume that the package @ng-rsbuild\/plugin-nx or Nx will eventually provide such logic that also automates handling secondary entry points out of the box as well as further API sugar for simplifying the configuration. <\/p>\n<h2>Important: Pin Versions of Angular Packages<\/h2>\n<p>The <code>shareAll<\/code> helper also uses the version numbers found in your <code>package.json<\/code>. For all Angular-based packages, you should pin these numbers by removing prefixes such as <code>^<\/code> or <code>~<\/code>. The reason is that currently, a compiled Angular application assumes to see exactly the same Angular version it was compiled with at runtime, as the compiled code is accessing Angular's private API. For such private APIs, there is no guarantee of semantic versioning. The good message is that there are some signs that this restriction might be removed in the future.<\/p>\n<h2>Configuring the Shell<\/h2>\n<p>The shell's rsbuild configuration in the file <code>shell\/rsbuild.config.ts<\/code> looks similar to the one used for the Micro Frontend:<\/p>\n<pre><code class=\"language-typescript\">import { createConfig } from &#039;@ng-rsbuild\/plugin-angular&#039;;\n\n\/\/ eslint-disable-next-line @nx\/enforce-module-boundaries\nimport { shareAll } from &#039;..\/mf.tools&#039;;\n\nexport default createConfig({\n  browser: &#039;.\/src\/main.ts&#039;,\n}, {\n  moduleFederation: {\n    options: {\n      name: &#039;shell&#039;,\n      shared: {\n        ...shareAll({\n          singleton: true,\n          strictVersion: true,\n        })\n      }\n    }\n  }\n});<\/code><\/pre>\n<p>As our shell isn't exposing any module, there is no <code>exposes<\/code> node.<\/p>\n<p>Also, the shell needs to be switched to asynchronous bootstrapping as discussed above. The <code>main.ts<\/code> uses the Module Federation runtime to initialize Federation. For this, we basically map the unique names of our Micro Frontends to their remote entries:<\/p>\n<pre><code class=\"language-typescript\">import { init } from &#039;@module-federation\/enhanced\/runtime&#039;;\n\ninit({\n  name: &#039;shell&#039;,\n  remotes: [\n    {\n      name: &quot;mfe1&quot;,\n      entry: &quot;http:\/\/localhost:4201\/remoteEntry.js&quot;,\n    }\n  ],\n});\n\nimport(&#039;.\/bootstrap&#039;);<\/code><\/pre>\n<p>Module Federation 2 provides a JSON-based manifest as a replacement for remote entries that consist of JavaScript code. This is a topic, I will look into in a further article. <\/p>\n<p>After initializing Federation, the application delegates to the <code>bootstrap.ts<\/code> containing the bootstrap logic usually found in the <code>main.ts<\/code>.<\/p>\n<h2>Loading the Micro Frontend<\/h2>\n<p>For loading the Micro Frontend, the example at hand uses a lazy route set up in <code>shell\/src\/app\/app.routes.ts<\/code>:<\/p>\n<pre><code class=\"language-typescript\">import { Route } from &#039;@angular\/router&#039;;\nimport { HomeComponent } from &#039;.\/home.component&#039;;\nimport { loadRemote } from &#039;@module-federation\/enhanced\/runtime&#039;;\nimport { Type } from &#039;@angular\/core&#039;;\n\nexport const appRoutes: Route[] = [\n    {\n        path: &#039;&#039;,\n        pathMatch: &#039;full&#039;,\n        component: HomeComponent\n    },\n    {\n        path: &#039;mfe1&#039;,\n        loadComponent: () =&gt; loadRemote(&#039;mfe1\/Component&#039;) as Promise&lt;Type&lt;unknown&gt;&gt;\n    }\n];<\/code><\/pre>\n<p>The <code>loadRemote<\/code> function provided by the Federation runtime loads the <code>AppComponent<\/code> from the Micro Frontend. As there is a default export for this component, we don't need to mention its name. The string <code>mfe1\/Component<\/code> points to the module, <code>mfe1<\/code> exposes as <code>.\/Component<\/code>.<\/p>\n<p>The example does not provide a fallback for the case, lazy loading <code>mfe1<\/code> does not work. In practice, there should be a <code>catch<\/code> handler, and we should handle <code>null<\/code> results showing that <code>loadRemote<\/code> was not successful<\/p>\n<p>Now, for loading our Micro Frontend, we need a respective <code>routerLink<\/code> and a <code>router-outlet<\/code> in our <code>app.component.ts<\/code>:<\/p>\n<pre><code class=\"language-html\">&lt;ul&gt;\n    &lt;li&gt;&lt;a routerLink=&quot;\/&quot;&gt;Home&lt;\/a&gt;&lt;\/li&gt;\n    &lt;li&gt;&lt;a routerLink=&quot;\/mfe1&quot;&gt;Flights&lt;\/a&gt;&lt;\/li&gt;\n&lt;\/ul&gt;\n\n&lt;router-outlet&gt;&lt;\/router-outlet&gt;<\/code><\/pre>\n<h2>Trying it out<\/h2>\n<p>To try out our Micro Frontend solution, start both applications in two different terminal windows:<\/p>\n<pre><code>nx dev mfe1 -o\nnx dev shell -o<\/code><\/pre>\n<h2>Bonus: Sharing Libs and Data<\/h2>\n<p>\ud83d\udd00 Branch: <code>shared-lib<\/code><\/p>\n<p>So far, we just shared third-party packages installed via npm. Obviously, we can share our own npm packages the same way. Such shared packaes can also be used to establish communication between Micro Frontends. An easy way for accomplishing this is adding an Angular service to such a shared package. As services are Singletons, one Micro Frontend can write into it and others can read it. By using data structures such as Observables, Subjects, or Signals, we can also notify Micro Frontends about value changes.<\/p>\n<p>To prevent publishing npm packages, we can also leverage a repo-internal library. In our case, we could, for instance, add an <code>auth<\/code> library managing the current user name:<\/p>\n<pre><code class=\"language-bash\">nx g lib auth<\/code><\/pre>\n<p>A simple service for sharing the user name could look as follows:<\/p>\n<pre><code class=\"language-typescript\">import { Injectable, signal } from &#039;@angular\/core&#039;;\n\n@Injectable({ providedIn: &#039;root&#039; })\nexport class AuthService {\n  userName = signal(&#039;&#039;);\n}<\/code><\/pre>\n<p>Also, we need to export this service via the library's public API:<\/p>\n<pre><code class=\"language-ts\">export * from &#039;.\/lib\/auth\/auth.component&#039;;\n\n\/\/ Add this export:\nexport * from &#039;.\/lib\/auth\/auth.service&#039;;<\/code><\/pre>\n<p>The next step is to configure the <code>auth<\/code> lib as a shared library. For this, the shared section in both rsbuild configurations gets the following entry:<\/p>\n<pre><code class=\"language-ts\">[...]\nshared: {\n  ...shareAll({\n    singleton: true,\n    strictVersion: true,\n  }),\n  &#039;@rspack-demo\/auth&#039;: {\n    singleton: true,\n    strictVersion: true,\n    version: &#039;0.0.0&#039;,\n    requiredVersion: &#039;0.0.0&#039;,\n    import: &#039;..\/auth\/src\/index.ts&#039;,\n  },\n}\n[...]<\/code><\/pre>\n<p>As here, we don't have a <code>package.json<\/code> that informs about the library's entry point, we need to specify it by hand via the <code>import<\/code> property. Also, we need to define the current version and the version range we accept (<code>requiredVersion<\/code>). In both cases, the example assigns <code>0.0.0<\/code> as it is assuming that a monorepo-internal library does not have a version. In complexer cases, you might want to assign version numbers so that, for instance, only the highest version from all deployed Micro Frontends is shared at runtime.<\/p>\n<p>\ud83d\udd00 Branch: <code>shared-lib-helper<\/code><\/p>\n<p>Also this kind of configuration can be automated via the <code>shareAll<\/code> helper: The branch <code>shared-lib-helper<\/code> contains a version of <a href=\"https:\/\/github.com\/manfredsteyer\/nx-rspack-mf-demo\/blob\/shared-lib-helper\/mf.tools.ts\">shareAll<\/a> that not only shares all dependencies found in your <code>package.json<\/code> but also all path mappings found in your <code>tsconfig.base.json<\/code> that point to such internal libraries:<\/p>\n<pre><code class=\"language-ts\">[...]\nshared: {\n  \/\/ \n  \/\/ now, shareAll takes care of both,\n  \/\/ packages and repo-internal libs\n  \/\/\n  ...shareAll({\n    singleton: true,\n    strictVersion: true,\n  }),\n},\n[...]<\/code><\/pre>\n<h2>Discussion and Outlook<\/h2>\n<p>With the community solution @ng-rsbuild\/plugin-nx that is published by the Nx team member Ferry Colum we now have the possibility to build Angular-solutions with rsbuild in our Nx workspaces. This improves the build times as, similar to other representatives of this tools generation, rsbuild and the underlying rspack are compiled into machine code and implemented with parallelization in mind. <\/p>\n<p>We will see whether this already justifies moving away from the Angular CLI's esbuild-based <code>ApplicationBuilder<\/code>, which is the de facto standard in the Angular space with similar characteristics (compiled to machine code, parallelization) and powers several of Angular's features such as SSR, Hybrid Rendering, and Incremental Hydration. <\/p>\n<p>However, even if we set the performance question aside, this package is still vital: It brings some competition to the play that might lead to improvements at both sides and it is the foundation for running the latest version of Module Federation including all the innovations that will eventually be added in a performant way in the Angular space. Saying this, while there are pros and cons on both sides, we also see a lot of potential in our Native Federation approach.<\/p>\n<p>A further advantage of the rsbuild integration is that it is designed to be <a href=\"https:\/\/rsbuild.dev\/guide\/start\/index\">compatible with most webpack plugins<\/a> and hence helps to migrate existing solutions to a more modern and faster build environment. Also, rspack is backed by Bytedance, the company behind TikTok and other brands, and there is already a vivid ecosystem with tools such as the static site generator rspress or the build analyzer rsdoctor. <\/p>\n<p>The possibility of using the same build tool for several frameworks in an Nx workspace is tempting. Giving people the choice of their favorite tools is a benefit Nx provides. As Colum told me, there is also the potential that this package helps foster a plugin community where people can benefit from rsbuild plugins more easily.<\/p>\n<p>Finally, I want to close this article with a huge shout-out to Colum Ferry, who invested a lot of time and energy into this integration, which provides the whole community with the mentioned advantages.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In just a few years, Module Federation grew from a first implementation that shipped with webpack 5 to a whole ecosystem. Meanwhile, we have an implementation for rspack, a port to vite, and a runtime that can be used across the whole ecosystem. There are also several third parties in this space: Zephyr offers a [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":27441,"comment_status":"open","ping_status":"open","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-27448","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Nx and Angular with Rspack and Module Federation - 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\/blog\/nx-with-rspack-and-module-federation\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Nx and Angular with Rspack and Module Federation - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"In just a few years, Module Federation grew from a first implementation that shipped with webpack 5 to a whole ecosystem. Meanwhile, we have an implementation for rspack, a port to vite, and a runtime that can be used across the whole ecosystem. There are also several third parties in this space: Zephyr offers a [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-02T21:04:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-01-03T14:04:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/read-now.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Manfred Steyer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/read-now.jpg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/\"},\"author\":{\"name\":\"Manfred Steyer\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\"},\"headline\":\"Nx and Angular with Rspack and Module Federation\",\"datePublished\":\"2025-01-02T21:04:26+00:00\",\"dateModified\":\"2025-01-03T14:04:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/\"},\"wordCount\":1757,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/\",\"name\":\"Nx and Angular with Rspack and Module Federation - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp\",\"datePublished\":\"2025-01-02T21:04:26+00:00\",\"dateModified\":\"2025-01-03T14:04:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp\",\"width\":1792,\"height\":1024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Nx and Angular with Rspack and Module Federation\"}]},{\"@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\/f3de69c1e2bdb5ba04d8d2f5f998b81a\",\"name\":\"Manfred Steyer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Nx and Angular with Rspack and Module Federation - 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\/blog\/nx-with-rspack-and-module-federation\/","og_locale":"en_US","og_type":"article","og_title":"Nx and Angular with Rspack and Module Federation - ANGULARarchitects","og_description":"In just a few years, Module Federation grew from a first implementation that shipped with webpack 5 to a whole ecosystem. Meanwhile, we have an implementation for rspack, a port to vite, and a runtime that can be used across the whole ecosystem. There are also several third parties in this space: Zephyr offers a [&hellip;]","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/","og_site_name":"ANGULARarchitects","article_published_time":"2025-01-02T21:04:26+00:00","article_modified_time":"2025-01-03T14:04:56+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/read-now.png","type":"image\/png"}],"author":"Manfred Steyer","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/read-now.jpg","twitter_misc":{"Written by":"Manfred Steyer","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/"},"author":{"name":"Manfred Steyer","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a"},"headline":"Nx and Angular with Rspack and Module Federation","datePublished":"2025-01-02T21:04:26+00:00","dateModified":"2025-01-03T14:04:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/"},"wordCount":1757,"commentCount":0,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/","name":"Nx and Angular with Rspack and Module Federation - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp","datePublished":"2025-01-02T21:04:26+00:00","dateModified":"2025-01-03T14:04:56+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2025\/01\/DALL\u00b7E-2025-01-02-22.01.15-A-creative-illustration-of-a-crab-dressed-as-a-construction-worker-wearing-a-yellow-hard-hat-and-a-tool-belt-holding-a-hammer-in-one-claw-and-bluepr.webp","width":1792,"height":1024},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/nx-with-rspack-and-module-federation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Nx and Angular with Rspack and Module Federation"}]},{"@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\/f3de69c1e2bdb5ba04d8d2f5f998b81a","name":"Manfred Steyer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","caption":"Manfred Steyer"}}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/27448","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\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=27448"}],"version-history":[{"count":4,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/27448\/revisions"}],"predecessor-version":[{"id":27459,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/27448\/revisions\/27459"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/27441"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=27448"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=27448"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=27448"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}