diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 03f93fbd57..9717ae2d29 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -652,6 +652,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Nx Module Federation Technical Overview", + "path": "/concepts/module-federation/nx-module-federation-technical-overview", + "id": "nx-module-federation-technical-overview", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Faster Builds with Module Federation", "path": "/concepts/module-federation/faster-builds-with-module-federation", @@ -849,6 +857,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Nx Module Federation Technical Overview", + "path": "/concepts/module-federation/nx-module-federation-technical-overview", + "id": "nx-module-federation-technical-overview", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Faster Builds with Module Federation", "path": "/concepts/module-federation/faster-builds-with-module-federation", @@ -884,6 +900,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Nx Module Federation Technical Overview", + "path": "/concepts/module-federation/nx-module-federation-technical-overview", + "id": "nx-module-federation-technical-overview", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Faster Builds with Module Federation", "path": "/concepts/module-federation/faster-builds-with-module-federation", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 2db422d6dd..d1ddfa1a57 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -888,6 +888,17 @@ "path": "/concepts/module-federation/module-federation-and-nx", "tags": ["module-federation", "angular", "react"] }, + { + "id": "nx-module-federation-technical-overview", + "name": "Nx Module Federation Technical Overview", + "description": "", + "mediaImage": "", + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview", + "itemList": [], + "isExternal": false, + "path": "/concepts/module-federation/nx-module-federation-technical-overview", + "tags": ["module-federation", "angular", "react"] + }, { "id": "faster-builds-with-module-federation", "name": "Faster Builds with Module Federation", @@ -1159,6 +1170,17 @@ "path": "/concepts/module-federation/module-federation-and-nx", "tags": ["module-federation", "angular", "react"] }, + { + "id": "nx-module-federation-technical-overview", + "name": "Nx Module Federation Technical Overview", + "description": "", + "mediaImage": "", + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview", + "itemList": [], + "isExternal": false, + "path": "/concepts/module-federation/nx-module-federation-technical-overview", + "tags": ["module-federation", "angular", "react"] + }, { "id": "faster-builds-with-module-federation", "name": "Faster Builds with Module Federation", @@ -1208,6 +1230,17 @@ "path": "/concepts/module-federation/module-federation-and-nx", "tags": ["module-federation", "angular", "react"] }, + "/concepts/module-federation/nx-module-federation-technical-overview": { + "id": "nx-module-federation-technical-overview", + "name": "Nx Module Federation Technical Overview", + "description": "", + "mediaImage": "", + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview", + "itemList": [], + "isExternal": false, + "path": "/concepts/module-federation/nx-module-federation-technical-overview", + "tags": ["module-federation", "angular", "react"] + }, "/concepts/module-federation/faster-builds-with-module-federation": { "id": "faster-builds-with-module-federation", "name": "Faster Builds with Module Federation", diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index e74fee7dc4..1c6b2879a3 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -675,6 +675,13 @@ "name": "Module Federation and Nx", "path": "/concepts/module-federation/module-federation-and-nx" }, + { + "description": "", + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview", + "id": "nx-module-federation-technical-overview", + "name": "Nx Module Federation Technical Overview", + "path": "/concepts/module-federation/nx-module-federation-technical-overview" + }, { "description": "", "file": "shared/concepts/module-federation/faster-builds", @@ -712,6 +719,13 @@ "name": "Module Federation and Nx", "path": "/concepts/module-federation/module-federation-and-nx" }, + { + "description": "", + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview", + "id": "nx-module-federation-technical-overview", + "name": "Nx Module Federation Technical Overview", + "path": "/concepts/module-federation/nx-module-federation-technical-overview" + }, { "description": "", "file": "shared/concepts/module-federation/faster-builds", @@ -742,6 +756,13 @@ "name": "Module Federation and Nx", "path": "/concepts/module-federation/module-federation-and-nx" }, + { + "description": "", + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview", + "id": "nx-module-federation-technical-overview", + "name": "Nx Module Federation Technical Overview", + "path": "/concepts/module-federation/nx-module-federation-technical-overview" + }, { "description": "", "file": "shared/concepts/module-federation/faster-builds", diff --git a/docs/map.json b/docs/map.json index 828592b3bc..2ee5104e63 100644 --- a/docs/map.json +++ b/docs/map.json @@ -268,6 +268,12 @@ "tags": ["module-federation", "angular", "react"], "file": "shared/concepts/module-federation/module-federation-and-nx" }, + { + "name": "Nx Module Federation Technical Overview", + "id": "nx-module-federation-technical-overview", + "tags": ["module-federation", "angular", "react"], + "file": "shared/concepts/module-federation/nx-module-federation-technical-overview" + }, { "name": "Faster Builds with Module Federation", "id": "faster-builds-with-module-federation", diff --git a/docs/shared/concepts/module-federation/module-federation-and-nx.md b/docs/shared/concepts/module-federation/module-federation-and-nx.md index a0c06813d2..4f8dc233f2 100644 --- a/docs/shared/concepts/module-federation/module-federation-and-nx.md +++ b/docs/shared/concepts/module-federation/module-federation-and-nx.md @@ -100,6 +100,16 @@ Nx offers out-of-the-box support for Module Federation with React and Angular. T - Versioning of Libraries - to aid in preventing some common issues regarding incompatible package versions being used by `federated modules` - Scaling DX - techniques to ensure a smooth DX regardless of the number of remotes in the workspace +### Develop as a User + +For both the best DX (Development Experience) and most accurate development of a Module Federation architecture we recommend viewing it as a single application. In other words, the `host` and all the `remotes` are composed to form a single application. + +The `host` is the entry point and the `remotes` are modules used by the application. It just happens that the `remotes` are fetched over-the-wire at runtime rather than being bundled into the application. + +To support this, as well as to ensure a great local DX, we built our Module Federation support in such a way that when developing locally you should always run `serve` on your `host` application. This will start up your full Module Federation architecture; serving your `host` with `webpack-dev-server` and each `remote` via a single `http-server`. You can learn more about this on our [Nx Module Federation Technical Overview](/concepts/module-federation/nx-module-federation-technical-overview). + +When you're working on a specific `remote` application, you should use the `--devRemotes` option to specify the `remote` you are currently developing; e.g. `nx serve host --devRemotes=remote1`. This ensures that the `remote` is served via `webpack-dev-server` allowing for HMR and live reloading. + ## Use Cases Nx has identified some common use cases that have made developers reach for Module Federation. They are Faster Builds and Independent Deployability. diff --git a/docs/shared/concepts/module-federation/module-federation-host-serve-light.png b/docs/shared/concepts/module-federation/module-federation-host-serve-light.png new file mode 100644 index 0000000000..eeda99b762 Binary files /dev/null and b/docs/shared/concepts/module-federation/module-federation-host-serve-light.png differ diff --git a/docs/shared/concepts/module-federation/nx-module-federation-technical-overview.md b/docs/shared/concepts/module-federation/nx-module-federation-technical-overview.md new file mode 100644 index 0000000000..dfc84a2998 --- /dev/null +++ b/docs/shared/concepts/module-federation/nx-module-federation-technical-overview.md @@ -0,0 +1,43 @@ +# Nx Module Federation Technical Overview + +Nx's Module Federation support is provided through a mixture of `executors` and the `withModuleFederation()` util that is used in you `webpack.config` file. Understanding what is happening under the hood can help when developing applications that use Module Federation as well as debugging any potential issues you run into. + +## What happens when you serve your host? + +When you serve your host application via `nx serve host`, the Nx `module-federation-dev-server` executor is invoked. This executor does a few things that aim to provide a more holistic local development while ensuring a great DX (development experience). + +{% callout type="note" title="Using Module Federation with SSR?" %} +The same technique outlined below also applies to the `module-federation-ssr-dev-server`. +This is important to know when it comes to deploying your SSR Module Federation application as it indicates that you can place the build artifacts from the `remotes` onto something like an AWS S3 Bucket and your `host` will be able to find these files correctly. +{% /callout %} + +The executor does the following: + +1. Finds all the `remotes` that the `host` depends on. +2. Determines which `remotes` need to be served statically and which need to be served via `webpack-dev-server`. +3. For the `static remotes`, it will invoke `nx run-many -t build --projects={listOfStaticRemotes}`. +4. If required, it will move the built artifacts of each `remote` to a common directory. +5. It will run `http-server` at the common directory such that those files are available on the network from a single port. +6. It will create proxy servers via `express` listening on the ports where each `remote` _should_ be located (as configured in the host's `module-federation.config.ts` or `module-federation.manifest.json` file). + - These proxy servers will proxy requests from the server to the `http-server` to fetch the correct files as requested by Module Federation. +7. If the `--devRemotes` option has been passed, it will serve each `dev remote` via `webpack-dev-server` allowing for HMR and live reloading when working on those remotes. +8. It will serve the `host` via `webpack-dev-server`. + +If you prefer diagrams, the one below outlines the above steps. + +![Nx Module Federation Host Serve Flow](/shared/concepts/module-federation/module-federation-host-serve-light.png) + +## The `NxRuntimeLibraryControlPlugin` + +Previously, when using shared workspace libraries as part of your Module Federation application, there was a chance that the workspace library would be provided by one of the `static remotes`. This would cause issues where changes to those shared libraries would not be reflected in the locally served application. + +To combat this issue, we developed the `NxRuntimeLibraryControlPlugin`. This is a [Runtime Plugin]() that will ensure that workspace libraries are only shared via any active `dev remote`. This means that any changes to the shared library will be picked up by `webpack-dev-server` and, as such, reflected in the locally served application. + +This plugin is enabled by default, however, you can turn it off in your `module-federation.config` file: + +```ts +export const config: ModuleFederationConfig = { + ..., + disableNxRuntimeLibraryControlPlugin: true +} +``` diff --git a/docs/shared/recipes/module-federation-with-ssr.md b/docs/shared/recipes/module-federation-with-ssr.md index f37b75abd0..f1b237767c 100644 --- a/docs/shared/recipes/module-federation-with-ssr.md +++ b/docs/shared/recipes/module-federation-with-ssr.md @@ -137,5 +137,6 @@ To serve the `store` application and watch for changes on the `checkout` applica To learn more about Module Federation, we have some resources you might find useful: +- [Concepts: Nx Module Federation Technical Overview](/concepts/module-federation/nx-module-federation-technical-overview) - [Guide: Faster Builds with Module Federation](/concepts/module-federation/faster-builds-with-module-federation) - [Video: Speed up your Angular serve and build times with Module Federation and Nx](https://www.youtube.com/watch?v=JkcaGzhRjkc) diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 1e720388e7..dc640d7a91 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -36,6 +36,7 @@ - [Buildable and Publishable Libraries](/concepts/buildable-and-publishable-libraries) - [Module Federation](/concepts/module-federation) - [Module Federation and Nx](/concepts/module-federation/module-federation-and-nx) + - [Nx Module Federation Technical Overview](/concepts/module-federation/nx-module-federation-technical-overview) - [Faster Builds with Module Federation](/concepts/module-federation/faster-builds-with-module-federation) - [Micro Frontend Architecture](/concepts/module-federation/micro-frontend-architecture) - [Manage Library Versions with Module Federation](/concepts/module-federation/manage-library-versions-with-module-federation)