Blog
Colum Ferry
September 12, 2024

Next-Gen Module Federation Deployments with Nx and Zephyr Cloud

Next-Gen Module Federation Deployments with Nx and Zephyr Cloud

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 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 and Netlify)
  • A beautiful UI to visualize your deployments

And so much more, Zephyr Cloud really is one of the best deployment solutions available.

Zephyr Cloud Features

You can learn more about the full feature set that Zephyr Cloud offers here.

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

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:

~

npx create-nx-workspace myorg

1NX Let's create a new workspace [https://nx.dev/getting-started/intro] 2 3✔ Which stack do you want to use? · none 4Package-based monorepo, integrated monorepo, or standalone project? · integrated 5✔ Which CI provider would you like to use? · github 6 7 NX Creating your v19.7.0 workspace. 8 9✔ Installing dependencies with npm 10✔ Successfully created the workspace: myorg. 11✔ Nx Cloud has been set up successfully 12✔ CI workflow has been generated successfully 13 14

Next, we'll want to navigate into our new workspace:

cd myorg

And finally, we'll add the @nx/react plugin to our workspace.

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.

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.

~/myorg

npx nx g @nx/react:host apps/shell --remotes=remote1 --bundler=rspack

1 NX Generating @nx/react:host 2 3✔ Which stylesheet format would you like to use? · css 4✔ Which E2E test runner would you like to use? · playwright 5Fetching prettier... 6Fetching @nx/rspack... 7Fetching @nx/playwright... 8Fetching @nx/jest... 9 10// REMOVED FOR BREVITY 11 12 NX 👀 View Details of shell 13 14Run "nx show project shell" to view details about this project. 15 16 NX 👀 View Details of remote1 17Run "nx show project remote1" to view details about this project. 18

With that, two applications will be added to our workspace shell and remote as well as their counterpart e2e projects.

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.

We specified --bundler=rspack indicating that the applications should be built with Rspack.
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:

shell/rspack.config.ts
1import { composePlugins, withNx, withReact } from '@nx/rspack'; 2import { 3 withModuleFederation, 4 ModuleFederationConfig, 5} from '@nx/rspack/module-federation'; 6 7import baseConfig from './module-federation.config'; 8 9const config: ModuleFederationConfig = { 10 ...baseConfig, 11}; 12 13// Nx plugins for rspack to build config object from Nx options and context. 14/** 15 * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation 16 * The DTS Plugin can be enabled by setting dts: true 17 * Learn more about the DTS Plugin here: https://module-federation.io/configure/dts.html 18 */ 19export default composePlugins( 20 withNx(), 21 withReact(), 22 withModuleFederation(config, { dts: false }) 23); 24

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.

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 and Runtime Plugins. 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.

Step 4: Building and Serving

To build all the applications in the workspace, run the following:

~/myorg

npx nx run-many -t build

1 2 ✔ nx run remote1:build:production (2s) 3 ✔ nx run shell:build:production (526ms) 4 5——————————————————————————————————————————————————————————————————————————————————————— 6 7 NX Successfully ran target build for 2 projects (3s) 8

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.

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 document.

Run the following command to serve the host application with the remote served statically:

~/myorg

npx nx serve shell

1> nx run shell:serve 2 3 4 NX Starting module federation dev-server for shell with 1 remotes 5 6 7 NX Building 1 static remotes... 8 9 10 NX Built 1 static remotes 11 12 13 NX Starting static remotes proxies... 14 15 16 NX Static remotes proxies started successfully 17 18[ Module Federation Manifest Plugin ]: Manifest will use absolute path resolution via its host at runtime, reason: publicPath='auto' 19<i> [webpack-dev-server] Project is running at: 20<i> [webpack-dev-server] Loopback: http://localhost:4200/, http://[::1]:4200/ 21<i> [webpack-dev-server] 404s will fallback to '/index.html' 22● ━━━━━━━━━━━━━━━━━━━━━━━━━ (70%) sealing after module optimization [ Module Federation Manifest Plugin ] Manifest Link: {auto}/mf-manifest.json 23● ━━━━━━━━━━━━━━━━━━━━━━━━━ (98%) emitting emit Starting up http-server, serving dist 24 25http-server version: 14.1.1 26 27http-server settings: 28CORS: true 29Cache: -1 seconds 30Connection Timeout: 120 seconds 31Directory Listings: visible 32AutoIndex: visible 33Serve GZIP Files: false 34Serve Brotli Files: false 35Default File Extension: none 36 37Available on: 38 http://localhost:4202 39Hit CTRL-C to stop the server 40 41 42 NX Server ready at http://localhost:4200 43

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.

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.

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:

shell/package.json
1{ 2 "name": "shell", 3 "version": "0.0.0" 4} 5

Once this is done, add all staged files and create a git commit.

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.

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.

If you don't already have the GitHub CLI installed, I would highly recommend it.

You can then run the following to create your GitHub Repository from your terminal:

~/myorg

gh repo create

1? What would you like to do? Push an existing local repository to GitHub 2? Path to local repository . 3? Repository name nx-zephyr-cloud-example 4? Repository owner Coly010 5? Description Example of Nx React Rspack Module Federation with Zephyr Cloud 6? Visibility Private 7✓ Created repository Coly010/nx-zephyr-cloud-example on GitHub 8 https://github.com/Coly010/nx-zephyr-cloud-example 9? Add a remote? Yes 10? What should the new remote be called? origin 11✓ Added remote https://github.com/Coly010/nx-zephyr-cloud-example.git 12? Would you like to push commits from the current branch to "origin"? Yes 13

Step 3: Add Zephyr Cloud

To add Zephyr Cloud itself, we need to install their zephyr-webpack-plugin.

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.

Run the following to install the plugin:

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:

1import { withZephyr } from 'zephyr-webpack-plugin'; 2 3export default composePlugins( 4 ..., 5 withZephyr() 6) 7

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:

shell/rspack.config.ts
1import { composePlugins, withNx, withReact } from '@nx/rspack'; 2import { 3 withModuleFederation, 4 ModuleFederationConfig, 5} from '@nx/rspack/module-federation'; 6import { withZephyr } from 'zephyr-webpack-plugin'; 7 8import baseConfig from './module-federation.config'; 9 10const config: ModuleFederationConfig = { 11 ...baseConfig, 12}; 13 14// Nx plugins for rspack to build config object from Nx options and context. 15/** 16 * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation 17 * The DTS Plugin can be enabled by setting dts: true 18 * Learn more about the DTS Plugin here: https://module-federation.io/configure/dts.html 19 */ 20export default composePlugins( 21 withNx(), 22 withReact(), 23 withModuleFederation(config, { dts: false }), 24 withZephyr() 25); 26

Step 4: First Deployment

With all the rspack.config.ts files updated, getting your first deployment is as simple as running:

~/myorg

npx nx run-many -t build --verbose

1> nx run remote1:build:production 2... 3 4 ZEPHYR Opening browser for authentication... 5 ZEPHYR Hi colum_nrwl_io! 6 ZEPHYR remote1.nx-zephyr-cloud-example.coly010#6 7 ZEPHYR 8 ZEPHYR Uploaded local snapshot in 152ms 9 ZEPHYR (12/12 assets uploaded in 235ms, 332.55kb) 10 ZEPHYR Deployed to Zephyr's edge in 352ms. 11 ZEPHYR 12 ZEPHYR https://colum_nrwl_io_6-remote1-nx-zephyr-cloud-example-c-e7ab3d770-ze.zephyrcloud.app 13 14... 15Rspack 1.0.4 compiled with 1 warning in 3.91 s 16 17> nx run shell:build:production 18... 19 20 ZEPHYR Hi colum_nrwl_io! 21 ZEPHYR shell.nx-zephyr-cloud-example.coly010#7 22 ZEPHYR 23 ZEPHYR Uploaded local snapshot in 165ms 24 ZEPHYR (10/10 assets uploaded in 202ms, 326.42kb) 25 ZEPHYR Deployed to Zephyr's edge in 248ms. 26 ZEPHYR 27 ZEPHYR https://colum_nrwl_io_7-shell-nx-zephyr-cloud-example-col-04ccb4027-ze.zephyrcloud.app 28 29... 30Rspack 1.0.4 compiled with 1 warning in 1.29 s 31

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):

~/myorg

npx nx run-many -t build --verbose

1> nx run remote1:build:production 2... 3 ZEPHYR https://colum_nrwl_io_6-remote1-nx-zephyr-cloud-example-c-e7ab3d770-ze.zephyrcloud.app 4 5 6> nx run shell:build:production 7... 8 ZEPHYR https://colum_nrwl_io_7-shell-nx-zephyr-cloud-example-col-04ccb4027-ze.zephyrcloud.app 9

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 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.

Learn More