--- title: Next-Gen Module Federation Deployments with Nx and Zephyr Cloud slug: next-gen-module-federation-deployment authors: ['Colum Ferry'] tags: [nx, module federation, rspack, zephyr cloud] cover_image: /blog/images/2024-09-12/next-gen-module-federation-deployments.avif published: true description: Learn how Nx and Zephyr Cloud simplify deploying Micro Frontends with Module Federation, making it easier to manage multiple build artifacts. --- Nx has supported Module Federation for a long time now and its popularity is seeing year-on-year increase. It has proven to be the defacto solution for modern Micro Frontends and Nx has embraced this and helped developers scaffold projects that use Module Federation; offering the most scalable and the most developer friendly experience to do so. However, we have always taken a step back when it came to the final piece of the puzzle: **Deployment**. Micro Frontends are, by their very nature, more complex to deploy. You are no longer deploying one build artifact but rather, many build artifacts that could even be on different release cadences from each other. And yet, we still expect the final application that our users interact with to be stable. There are so many approaches to deployments - think Kubernetes, Storage Buckets with DNS, EC2 instances etc - that it has always been difficult for us to recommend a solution. That was until [Zephyr Cloud](https://www.zephyr-cloud.io/) entered the game. Zephyr Cloud is a "bring your own cloud" deployment platform with best-in-class support for module federation projects that integrates right into your application build, providing seamless deployments without having to learn any new commands. With features such as: - Auto-deployment on build - Live Preview link generation - Version rollback and roll-forward - Micro Frontend dependency management - A Chrome Extension to manage environments - Support for a wide range of Cloud Platforms (such as [Cloudflare](https://www.cloudflare.com/en-gb/) and [Netlify](https://www.netlify.com/)) - A beautiful UI to visualize your deployments And so much more, Zephyr Cloud really is one of the best deployment solutions available. {% callout type="note" title="Zephyr Cloud Features" %} You can learn more about the full feature set that Zephyr Cloud offers [here](https://docs.zephyr-cloud.io/#main-features). {% /callout %} I myself, Colum Ferry, after having been allowed to experiment with it in its infancy back in February 2024 said > Zephyr Cloud is the Micro Frontend orchestration tool you never knew you needed. > What they have built will change the deployments for the better. > Think of the disruption k8s caused. Zephyr Cloud will do the same for the Micro Frontend world. > > _Reference: [Linkedin](https://www.linkedin.com/posts/colum-ferry-3a36a9169_zephyr-cloud-is-the-micro-frontend-orchestration-activity-7183207192991289344-6mSR)_ And I stand by that statement. Therefore, in this article I'll show you how to set up React Module Federation with Nx and Rspack and how to integrate it with Zephyr Cloud for deployment. ## Step 1: Set Up the Nx Workspace We'll start by creating an empty Nx workspace: ```{% command="npx create-nx-workspace myorg" path="~" %} NX Let's create a new workspace [https://nx.dev/getting-started/intro] ✔ Which stack do you want to use? · none ✔ Package-based monorepo, integrated monorepo, or standalone project? · integrated ✔ Which CI provider would you like to use? · github NX Creating your v19.7.0 workspace. ✔ Installing dependencies with npm ✔ Successfully created the workspace: myorg. ✔ Nx Cloud has been set up successfully ✔ CI workflow has been generated successfully ``` Next, we'll want to navigate into our new workspace: ```shell cd myorg ``` And finally, we'll add the [`@nx/react`](/nx-api/react) plugin to our workspace. ```shell npx nx add @nx/react ``` ## Step 2: Scaffold the Module Federation Projects Now that we have the `@nx/react` package installed, we have access to all the generators it offers. We'll use the `host` generator now to scaffold out Module Federation projects. {% callout type="note" title="Generating host applications" %} If you'd like a more indepth recipe for scaffolding `host` and `remote` generators you can take a look through our [Module Federation Recipes](/technologies/module-federation/recipes). {% /callout %} ```{% command="npx nx g @nx/react:host apps/shell --remotes=remote1 --bundler=rspack" path="~/myorg" %} NX Generating @nx/react:host ✔ Which stylesheet format would you like to use? · css ✔ Which E2E test runner would you like to use? · playwright Fetching prettier... Fetching @nx/rspack... Fetching @nx/playwright... Fetching @nx/jest... // REMOVED FOR BREVITY NX 👀 View Details of shell Run "nx show project shell" to view details about this project. NX 👀 View Details of remote1 Run "nx show project remote1" to view details about this project. ``` With that, two applications will be added to our workspace `shell` and `remote` as well as their counterpart e2e projects. {% callout type="note" title="Running tasks" %} These projects contain all the usual tasks you would expect to see with a Nx project such as `build`, `serve`, `test`, `lint`. You can learn more about Running Tasks in Nx [here](/features/run-tasks). {% /callout %} We specified `--bundler=rspack` indicating that the applications should be built with [Rspack](https://rspack.dev/). _This support has been newly added to Nx since Nx 19.7.0._ You'll note the `shell/rspack.config.ts` file. It's contents should match the following: ```ts {% fileName="shell/rspack.config.ts" %} import { composePlugins, withNx, withReact } from '@nx/rspack'; import { withModuleFederation, ModuleFederationConfig, } from '@nx/rspack/module-federation'; import baseConfig from './module-federation.config'; const config: ModuleFederationConfig = { ...baseConfig, }; // Nx plugins for rspack to build config object from Nx options and context. /** * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation * The DTS Plugin can be enabled by setting dts: true * Learn more about the DTS Plugin here: https://module-federation.io/configure/dts.html */ export default composePlugins( withNx(), withReact(), withModuleFederation(config, { dts: false }) ); ``` If you have experience with our `webpack` Module Federation support, you'll note that this file is very similar to the `webpack.config.ts` files we would have generated. The only real difference is that the imports point to `@nx/rspack`. {% callout type="note" title="Module Federation 2.0" %} Module Federation is still under active development, however, all new development is being included in Rspack as well as the `@module-federation/enhanced` package. Module Federation 2.0 brings new features such as [Federation Runtime](https://module-federation.io/guide/basic/runtime.html) and [Runtime Plugins](https://module-federation.io/plugin/dev/index.html). These are significant advancements which offer a vast range of capabilities to Module Federation projects. Nx itself has employed this strategy to solve a long-standing issue with shared workspace libraries wherein there was the possibility that a shared library would be served from a static remote. This in turn would prevent HMR updates to the library from being reflected in the locally served application. You can learn more about the `NxRuntimeLibraryControlPlugin` [here](/technologies/module-federation/concepts/nx-module-federation-technical-overview). {% /callout %} ## Step 4: Building and Serving To build all the applications in the workspace, run the following: ```{% command="npx nx run-many -t build" path="~/myorg" %} ✔ nx run remote1:build:production (2s) ✔ nx run shell:build:production (526ms) ——————————————————————————————————————————————————————————————————————————————————————— NX Successfully ran target build for 2 projects (3s) ``` This will build the applications with Rspack. You can observe the build artifacts in the `dist/` folder. To serve the Module Federation setup, we recommend only serving the `host` application. {% callout type="note" title="Serving all Module Federation Projects" %} Nx purpose-built a `serve` executor for Module Federation Projects. This executor will find all the `remote` applications that the `host` depends on and serves them, either statically or with HMR/Live Reloading. Serving statically means that we can reuse the build artifacts for the `remotes` for a faster dev-server startup time that is scalable. Combined with Nx caching, this works well to ensure a great developer experience. You can learn more about how this works in our [Nx Module Federation Technical Overview](/technologies/module-federation/concepts/nx-module-federation-technical-overview#what-happens-when-you-serve-your-host) document. {% /callout %} Run the following command to serve the `host` application with the `remote` served statically: ```{% command="npx nx serve shell" path="~/myorg" %} > nx run shell:serve NX Starting module federation dev-server for shell with 1 remotes NX Building 1 static remotes... NX Built 1 static remotes NX Starting static remotes proxies... NX Static remotes proxies started successfully [ Module Federation Manifest Plugin ]: Manifest will use absolute path resolution via its host at runtime, reason: publicPath='auto' [webpack-dev-server] Project is running at: [webpack-dev-server] Loopback: http://localhost:4200/, http://[::1]:4200/ [webpack-dev-server] 404s will fallback to '/index.html' ● ━━━━━━━━━━━━━━━━━━━━━━━━━ (70%) sealing after module optimization [ Module Federation Manifest Plugin ] Manifest Link: {auto}/mf-manifest.json ● ━━━━━━━━━━━━━━━━━━━━━━━━━ (98%) emitting emit Starting up http-server, serving dist http-server version: 14.1.1 http-server settings: CORS: true Cache: -1 seconds Connection Timeout: 120 seconds Directory Listings: visible AutoIndex: visible Serve GZIP Files: false Serve Brotli Files: false Default File Extension: none Available on: http://localhost:4202 Hit CTRL-C to stop the server NX Server ready at http://localhost:4200 ``` If you navigate to `http://localhost:4200` your application will render and you'll be able to navigate between the `host` and the `remote`. ## Step 4: Deployment Granted what we have currently is not something you'd likely see in a production application, we'll use it as is to demonstrate deployment with Zephyr Cloud. {% callout type="note" title="Zephyr Cloud Nx Recipe" %} Zephyr Cloud also has a recipe that you can follow to set up Nx React Module Federation with Zephyr Cloud [here](https://docs.zephyr-cloud.io/recipes/react-rspack-nx). {% /callout %} I'll break this section into sub-steps to make it easier to follow. ### Step 1: Add `package.json` and First Commit First, we need to add `package.json` files to our `shell` and `remote1` projects. This is used by Zephyr Cloud to determine the name and version of the projects for deployment. Create the following files: {% tabs %} {% tab label="shell/package.json" %} ```json {% fileName="shell/package.json" %} { "name": "shell", "version": "0.0.0" } ``` {% /tab %} {% tab label="remote1/package.json" %} ```json {% fileName="remote1/package.json" %} { "name": "remote1", "version": "0.0.0" } ``` {% /tab %} {% /tabs %} Once this is done, add all staged files and create a git commit. ```shell git add . git commit -m "initial commit" ``` ### Step 2: Create a GitHub Repository Next, we need to add a GitHub repository. It can be public or private, it will not affect the deployments by Zephyr Cloud. {% callout type="note" title="Why is this needed?" %} Behind the scene, Zephyr Cloud will map your git configuration (remote origin url, organization or username, repository name and branch) to deploy your application. Without this step the deployment will fail. {% /callout %} If you don't already have the [GitHub CLI](https://cli.github.com/) installed, I would highly recommend it. You can then run the following to create your GitHub Repository from your terminal: ```{% command="gh repo create" path="~/myorg" %} ? What would you like to do? Push an existing local repository to GitHub ? Path to local repository . ? Repository name nx-zephyr-cloud-example ? Repository owner Coly010 ? Description Example of Nx React Rspack Module Federation with Zephyr Cloud ? Visibility Private ✓ Created repository Coly010/nx-zephyr-cloud-example on GitHub https://github.com/Coly010/nx-zephyr-cloud-example ? Add a remote? Yes ? What should the new remote be called? origin ✓ Added remote https://github.com/Coly010/nx-zephyr-cloud-example.git ? Would you like to push commits from the current branch to "origin"? Yes ``` ### Step 3: Add Zephyr Cloud To add Zephyr Cloud itself, we need to install their `zephyr-webpack-plugin`. {% callout type="note" title="Rspack and Webpack Interop" %} The plugin is indeed written for Webpack, however, one of the big advantages of Rspack is the interoperability it offers for the Webpack Ecosystem. You can learn more about this compatability [here](https://rspack.dev/guide/compatibility/plugin). {% /callout %} Run the following to install the plugin: ```shell npm install zephyr-webpack-plugin ``` Now that the plugin has been installed in our workspace, we need to update the `rspack.config.ts` files to use it. This is a very simple two line change: ```ts import { withZephyr } from 'zephyr-webpack-plugin'; export default composePlugins( ..., withZephyr() ) ``` You'll need to make these updates to the following files: - `shell/rspack.config.ts` - `shell/rspack.config.prod.ts` - `remote1/rspack.config.ts` For example, your `shell/rspack.config.ts` file should now match the following: ```ts {% fileName="shell/rspack.config.ts" %} import { composePlugins, withNx, withReact } from '@nx/rspack'; import { withModuleFederation, ModuleFederationConfig, } from '@nx/rspack/module-federation'; import { withZephyr } from 'zephyr-webpack-plugin'; import baseConfig from './module-federation.config'; const config: ModuleFederationConfig = { ...baseConfig, }; // Nx plugins for rspack to build config object from Nx options and context. /** * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation * The DTS Plugin can be enabled by setting dts: true * Learn more about the DTS Plugin here: https://module-federation.io/configure/dts.html */ export default composePlugins( withNx(), withReact(), withModuleFederation(config, { dts: false }), withZephyr() ); ``` ### Step 4: First Deployment With all the `rspack.config.ts` files updated, getting your first deployment is as simple as running: ```{% command="npx nx run-many -t build --verbose" path="~/myorg" %} > nx run remote1:build:production ... ZEPHYR Opening browser for authentication... ZEPHYR Hi colum_nrwl_io! ZEPHYR remote1.nx-zephyr-cloud-example.coly010#6 ZEPHYR ZEPHYR Uploaded local snapshot in 152ms ZEPHYR (12/12 assets uploaded in 235ms, 332.55kb) ZEPHYR Deployed to Zephyr's edge in 352ms. ZEPHYR ZEPHYR https://colum_nrwl_io_6-remote1-nx-zephyr-cloud-example-c-e7ab3d770-ze.zephyrcloud.app ... Rspack 1.0.4 compiled with 1 warning in 3.91 s > nx run shell:build:production ... ZEPHYR Hi colum_nrwl_io! ZEPHYR shell.nx-zephyr-cloud-example.coly010#7 ZEPHYR ZEPHYR Uploaded local snapshot in 165ms ZEPHYR (10/10 assets uploaded in 202ms, 326.42kb) ZEPHYR Deployed to Zephyr's edge in 248ms. ZEPHYR ZEPHYR https://colum_nrwl_io_7-shell-nx-zephyr-cloud-example-col-04ccb4027-ze.zephyrcloud.app ... Rspack 1.0.4 compiled with 1 warning in 1.29 s ``` At this point, a page will likely be opened in your browser where you can create your Zephyr Cloud account and authenticate the CLI to allow it to deploy the applications to your account. You'll note that the output from this is not the same as the output we received earlier when we ran `npx nx run-many -t build`. In particular, the most recent set of logs contains the URLs of the deployed application (_Note: your URL should be different_): ```{% command="npx nx run-many -t build --verbose" path="~/myorg" %} > nx run remote1:build:production ... ZEPHYR https://colum_nrwl_io_6-remote1-nx-zephyr-cloud-example-c-e7ab3d770-ze.zephyrcloud.app > nx run shell:build:production ... ZEPHYR https://colum_nrwl_io_7-shell-nx-zephyr-cloud-example-col-04ccb4027-ze.zephyrcloud.app ``` Zephyr Cloud deployed our applications _during_ the build process! With Zephyr Cloud, it really is _that_ easy to deploy your Module Federation Projects. You can then visit the [Zephyr Cloud Dashboard](https://app.zephyr-cloud.io/) where you can get a more visual insight into your deployed projects. ## Conclusion Deploying Micro Frontend applications has always been a complex task, especially when it comes to managing multiple build artifacts and maintaining stability. However, with Nx's continued support for Module Federation and the integration of Zephyr Cloud, developers now have access to a streamlined, scalable solution that simplifies the deployment process significantly. Zephyr Cloud's unique features, such as auto-deployment, live preview links, and seamless rollback capabilities, make it an invaluable tool for Micro Frontend orchestration. By following the steps outlined in this guide, you can effortlessly set up your Nx workspace, scaffold Module Federation projects, and leverage Zephyr Cloud for quick, hassle-free deployments. For more information about Zephyr Cloud I highly recommend checking out their [docs](https://docs.zephyr-cloud.io/). ## Learn More - [Nx on CI](/ci/intro/ci-with-nx) - [Task Distribution with Nx Agents](/ci/features/distribute-task-execution) - [Automated e2e Test Splitting](/ci/features/split-e2e-tasks) - [X/Twitter](https://twitter.com/nxdevtools) -- [LinkedIn](https://www.linkedin.com/company/nrwl/) - [Nx Official Discord Server](https://go.nx.dev/community) - [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)