diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 7e49fb8718..4f833d7113 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -1924,6 +1924,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "How to create a Module Federation Remote Application", + "path": "/recipes/module-federation/create-a-remote", + "id": "create-a-remote", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "disableCollapsible": false @@ -3290,6 +3298,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "How to create a Module Federation Remote Application", + "path": "/recipes/module-federation/create-a-remote", + "id": "create-a-remote", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "disableCollapsible": false @@ -3302,6 +3318,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "How to create a Module Federation Remote Application", + "path": "/recipes/module-federation/create-a-remote", + "id": "create-a-remote", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Enforce Module Boundaries", "path": "/recipes/enforce-module-boundaries", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 461766fc73..059622ad75 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -2398,6 +2398,16 @@ "isExternal": false, "path": "/recipes/module-federation/create-a-host", "tags": [] + }, + { + "id": "create-a-remote", + "name": "How to create a Module Federation Remote Application", + "description": "A guide on how to create a Module Federation Remote Application in your Nx workspace", + "file": "shared/recipes/module-federation/creating-a-remote", + "itemList": [], + "isExternal": false, + "path": "/recipes/module-federation/create-a-remote", + "tags": [] } ], "isExternal": false, @@ -4102,6 +4112,16 @@ "isExternal": false, "path": "/recipes/module-federation/create-a-host", "tags": [] + }, + { + "id": "create-a-remote", + "name": "How to create a Module Federation Remote Application", + "description": "A guide on how to create a Module Federation Remote Application in your Nx workspace", + "file": "shared/recipes/module-federation/creating-a-remote", + "itemList": [], + "isExternal": false, + "path": "/recipes/module-federation/create-a-remote", + "tags": [] } ], "isExternal": false, @@ -4118,6 +4138,16 @@ "path": "/recipes/module-federation/create-a-host", "tags": [] }, + "/recipes/module-federation/create-a-remote": { + "id": "create-a-remote", + "name": "How to create a Module Federation Remote Application", + "description": "A guide on how to create a Module Federation Remote Application in your Nx workspace", + "file": "shared/recipes/module-federation/creating-a-remote", + "itemList": [], + "isExternal": false, + "path": "/recipes/module-federation/create-a-remote", + "tags": [] + }, "/recipes/enforce-module-boundaries": { "id": "enforce-module-boundaries", "name": "Enforce Module Boundaries", diff --git a/docs/map.json b/docs/map.json index e2726f93f2..7e09d1f34d 100644 --- a/docs/map.json +++ b/docs/map.json @@ -827,6 +827,12 @@ "name": "How to create a Module Federation Host Application", "description": "A guide on how to create a Module Federation Host Application in your Nx workspace", "file": "shared/recipes/module-federation/creating-a-host" + }, + { + "id": "create-a-remote", + "name": "How to create a Module Federation Remote Application", + "description": "A guide on how to create a Module Federation Remote Application in your Nx workspace", + "file": "shared/recipes/module-federation/creating-a-remote" } ] }, diff --git a/docs/shared/recipes/module-federation/creating-a-remote.md b/docs/shared/recipes/module-federation/creating-a-remote.md new file mode 100644 index 0000000000..37246a90ed --- /dev/null +++ b/docs/shared/recipes/module-federation/creating-a-remote.md @@ -0,0 +1,252 @@ +# Creating a Remote + +In the concept of Module Federation a `remote` is the term given to an application that exposes modules that can be +shared to and consumed by host applications. +This is the key difference between a `remote` and `host`. + +- A `remote` exposes modules that can be consumed +- A `host` consumes exposed modules + +**Nx** includes first-class support for helping you to scaffold a Module Federation Architecture for your React and +Angular application(s). + +## Generating a Remote + +To generate a remote application in your workspace, run the following command: + +{% tabs %} +{% tab label="React" %} + +```{% command="nx g @nx/react:remote myremote --directory=apps/react/myremote" %} +> NX Generating @nx/react:remote + +CREATE apps/react/myremote/src/app/app.spec.tsx +CREATE apps/react/myremote/src/assets/.gitkeep +CREATE apps/react/myremote/src/environments/environment.prod.ts +CREATE apps/react/myremote/src/environments/environment.ts +CREATE apps/react/myremote/src/favicon.ico +CREATE apps/react/myremote/src/index.html +CREATE apps/react/myremote/tsconfig.app.json +CREATE apps/react/myremote/webpack.config.ts +CREATE apps/react/myremote/.babelrc +CREATE apps/react/myremote/src/app/nx-welcome.tsx +CREATE apps/react/myremote/src/app/app.module.css +CREATE apps/react/myremote/src/app/app.tsx +CREATE apps/react/myremote/src/styles.css +CREATE apps/react/myremote/tsconfig.json +CREATE apps/react/myremote/project.json +CREATE apps/react/myremote/.eslintrc.json +CREATE apps/react/myremote/jest.config.ts +CREATE apps/react/myremote/tsconfig.spec.json +CREATE apps/react/myremote/src/bootstrap.tsx +CREATE apps/react/myremote/module-federation.config.ts +CREATE apps/react/myremote/src/main.ts +CREATE apps/react/myremote/src/remote-entry.ts +CREATE apps/react/myremote/webpack.config.prod.ts +UPDATE tsconfig.base.json +``` + +{% /tab %} +{% tab label="Angular" %} + +```{% command="nx g @nx/angular:remote myremote --directory=apps/angular/myremote" %} +> NX Generating @nx/angular:host + +CREATE apps/angular/myremote/project.json +CREATE apps/angular/myremote/src/assets/.gitkeep +CREATE apps/angular/myremote/src/favicon.ico +CREATE apps/angular/myremote/src/index.html +CREATE apps/angular/myremote/src/styles.css +CREATE apps/angular/myremote/tsconfig.app.json +CREATE apps/angular/myremote/tsconfig.editor.json +CREATE apps/angular/myremote/tsconfig.json +CREATE apps/angular/myremote/src/app/app.component.ts +CREATE apps/angular/myremote/src/app/app.module.ts +CREATE apps/angular/myremote/src/app/app.routes.ts +CREATE apps/angular/myremote/src/main.ts +CREATE apps/angular/myremote/.eslintrc.json +CREATE apps/angular/myremote/jest.config.ts +CREATE apps/angular/myremote/src/test-setup.ts +CREATE apps/angular/myremote/tsconfig.spec.json +CREATE apps/angular/myremote/src/app/remote-entry/entry.component.ts +CREATE apps/angular/myremote/src/app/remote-entry/entry.module.ts +CREATE apps/angular/myremote/src/app/remote-entry/entry.routes.ts +CREATE apps/angular/myremote/src/app/remote-entry/nx-welcome.component.ts +CREATE apps/angular/myremote/module-federation.config.ts +CREATE apps/angular/myremote/webpack.config.ts +CREATE apps/angular/myremote/webpack.prod.config.ts +CREATE apps/angular/myremote/src/bootstrap.ts +UPDATE tsconfig.base.json +``` + +{% /tab %} +{% /tabs %} + +After the `remote` application is generated, you can then update your host application's Module Federation Config File +to specify that it can consume federated modules from this remote. + +{% tabs %} +{% tab label="TypeScript Config File" %} + +```typescript {% fileName="apps/react/shell/module-federation.config.ts" %} +import { ModuleFederationConfig } from '@nx/webpack'; + +const config: ModuleFederationConfig = { + name: 'shell', + remotes: ['myremote'], // <-- add the name of your remote to the remotes array +}; +export default config; +``` + +{% /tab %} + +{% tab label="JavaScript Config File" %} + +```typescript {% fileName="apps/react/shell/module-federation.config.js" %} +module.exports = { + name: 'shell', + remotes: ['myremote'], // <-- add the name of your remote to the remotes array +}; +``` + +{% /tab %} +{% /tabs %} + +{% callout type="note" title="Creating a Host" %} +If you do not already have a host application in your workspace, look at +the [Create a Host Recipe](/recipes/module-federation/create-a-host) for more information on how to achieve +this. +{% /callout %} + +### Let Nx add your Remote to your Host + +The `remote` generators also allow you to specify a `--host` option, which will allow the generator to add your remote +to your host automatically. This can save you time by skipping the manual step above. +The command would look like the following: + +{% tabs %} +{% tab label="React" %} + +```{% command="nx g @nx/react:remote myremote --directory=apps/react/myremote --host=shell" %} +> NX Generating @nx/react:remote + +CREATE apps/react/myremote/src/app/app.spec.tsx +CREATE apps/react/myremote/src/assets/.gitkeep +CREATE apps/react/myremote/src/environments/environment.prod.ts +CREATE apps/react/myremote/src/environments/environment.ts +CREATE apps/react/myremote/src/favicon.ico +CREATE apps/react/myremote/src/index.html +CREATE apps/react/myremote/tsconfig.app.json +CREATE apps/react/myremote/webpack.config.ts +CREATE apps/react/myremote/.babelrc +CREATE apps/react/myremote/src/app/nx-welcome.tsx +CREATE apps/react/myremote/src/app/app.module.css +CREATE apps/react/myremote/src/app/app.tsx +CREATE apps/react/myremote/src/styles.css +CREATE apps/react/myremote/tsconfig.json +CREATE apps/react/myremote/project.json +CREATE apps/react/myremote/.eslintrc.json +CREATE apps/react/myremote/jest.config.ts +CREATE apps/react/myremote/tsconfig.spec.json +CREATE apps/react/myremote/src/bootstrap.tsx +CREATE apps/react/myremote/module-federation.config.ts +CREATE apps/react/myremote/src/main.ts +CREATE apps/react/myremote/src/remote-entry.ts +CREATE apps/react/myremote/webpack.config.prod.ts +UPDATE apps/react/shell/module-federation.config.ts +UPDATE tsconfig.base.json +``` + +{% /tab %} +{% tab label="Angular" %} + +```{% command="nx g @nx/angular:remote myremote --directory=apps/angular/myremote --host=shell" %} +> NX Generating @nx/angular:host + +CREATE apps/angular/myremote/project.json +CREATE apps/angular/myremote/src/assets/.gitkeep +CREATE apps/angular/myremote/src/favicon.ico +CREATE apps/angular/myremote/src/index.html +CREATE apps/angular/myremote/src/styles.css +CREATE apps/angular/myremote/tsconfig.app.json +CREATE apps/angular/myremote/tsconfig.editor.json +CREATE apps/angular/myremote/tsconfig.json +CREATE apps/angular/myremote/src/app/app.component.ts +CREATE apps/angular/myremote/src/app/app.module.ts +CREATE apps/angular/myremote/src/app/app.routes.ts +CREATE apps/angular/myremote/src/main.ts +CREATE apps/angular/myremote/.eslintrc.json +CREATE apps/angular/myremote/jest.config.ts +CREATE apps/angular/myremote/src/test-setup.ts +CREATE apps/angular/myremote/tsconfig.spec.json +CREATE apps/angular/myremote/src/app/remote-entry/entry.component.ts +CREATE apps/angular/myremote/src/app/remote-entry/entry.module.ts +CREATE apps/angular/myremote/src/app/remote-entry/entry.routes.ts +CREATE apps/angular/myremote/src/app/remote-entry/nx-welcome.component.ts +CREATE apps/angular/myremote/module-federation.config.ts +CREATE apps/angular/myremote/webpack.config.ts +CREATE apps/angular/myremote/webpack.prod.config.ts +CREATE apps/angular/myremote/src/bootstrap.ts +UPDATE apps/angular/shell/module-federation.config.ts +UPDATE tsconfig.base.json +``` + +{% /tab %} +{% /tabs %} + +## Building your Remote + +Your `remote` application acts like any other application in the context of Nx, and therefore building it as simple as +running: + +```shell +nx build myremote +``` + +## Serving your Remote + +The `remote` application is generated with two serve-like targets. These are: + +- serve +- serve-static + +They can be run as usual with Nx: + +```shell +nx serve myremote +nx serve-static myremote +``` + +### Serve Target + +The `serve` target will use `webpack-dev-server` to serve your application, allowing for HMR and Live Reload. This is +useful when you're working locally on that specific remote application. + +### Serve-Static Target + +The `serve-static` target will first build your application, storing the build artifact in the defined output directory +_(usually `dist/path/to/remote`)_. It will then use `http-server` to serve the built application locally. +This is less memory and CPU intensive than `webpack-dev-server` but it does not support HMR or Live Reload. + +The purpose of the `serve-static` target is to allow you to serve your `host` application, along with all of +the `remote` applications it depends on without being too resource intensive. + +### Serving your Remote via your Host + +Generally, your `host` is the main application that you deploy and that users visit. It consumes modules from `remote` +applications, but those `remote` applications are usually never visited directly by a user. +Therefore, to support developing your application in a manner that replicates how users use the application, when +serving a `host` application, Nx will serve all the dependent remotes automatically. + +By default, the dependent `remote` applications will be served via the `serve-static` command. However, if you are +working on a specific remote application, you can tell Nx to serve the `host` application and any number of `remote` +applications via the `webpack-dev-server` allowing those remote applications to take advantage of HMR and Live Reloading +as you work on them. + +To do this, run the command: + +```shell +nx serve host --devRemotes=myremote +``` + +This informs Nx to run the `serve` command of `myremote`, rather than the `serve-static` command. diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index ed15552c49..c2d4bceaab 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -138,6 +138,7 @@ - [Webpack plugins](/recipes/webpack/webpack-plugins) - [Module Federation](/recipes/module-federation) - [How to create a Module Federation Host Application](/recipes/module-federation/create-a-host) + - [How to create a Module Federation Remote Application](/recipes/module-federation/create-a-remote) - [Enforce Module Boundaries](/recipes/enforce-module-boundaries) - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions)