React + Rspack + Nx

Prerequisites

If you don't have nvm to manage your node version yet, head to the official nvm guide to install it.

1nvm use 20

Setup

1. Create a react app

Once the prerequisites are fulfilled, we can start in the terminal:

Terminal
1npx create-nx-workspace@latest my-first-mf-app --preset=react-standalone

The creation process will ask you:

1Need to install the following packages:
2[email protected]
3Ok to proceed? (y)

Press

y +
Enter
and then choose the following highlighted options.

Choose Rspack as bundler option.

1NX   Let's create a new workspace [https://nx.dev/getting-started/intro]
2
3? Which bundler would you like to use? …
4Vite    [ https://vitejs.dev/     ]
5Webpack [ https://webpack.js.org/ ]
6Rspack  [ https://www.rspack.dev/ ]

Choose None.

1✔ Which bundler would you like to use? · rspack
2? Test runner to use for end to end (E2E) tests …
3Playwright [ https://playwright.dev/ ]
4Cypress [ https://www.cypress.io/ ]
5None

When you are prompted to choose styling solution - choose Tailwind.

1? Default stylesheet format2CSS
3SASS(.scss)       [ https://sass-lang.com   ]
4LESS              [ https://lesscss.org     ]
5tailwind          [ https://tailwindcss.com     ]
6styled-components [ https://styled-components.com            ]
7emotion           [ https://emotion.sh                       ]
8styled-jsx        [ https://www.npmjs.com/package/styled-jsx ]

Choose Skip for now when you are asked to choose CI.

1? Set up CI with caching, distribution and test deflaking …
2(it's free and can be disabled any time)
3Yes, for GitHub Actions with Nx Cloud
4Yes, for CircleCI with Nx Cloud
5Skip for now

Choose Skip for now when you are asked for remote caching option

1? Would you like remote caching to make your build faster? …
2(it's free and can be disabled any time)
3Yes
4Skip for now

You can see the code up to this stage here:

. If you want to use our examples to try a deployment, remember to fork it.

Why fork it

When you are trying to deploy an application, Zephyr will figure out if you have write_access based on which organization the repository belong to. Thus if you fork it, it will be under your organization and you will be able to deploy.

4. Adding Zephyr

Open the project folder we created with code editor of your choice. Within current working directory, install Zephyr's plugin by running:

Terminal
1npm i zephyr-webpack-plugin

After install the plugin, open the file rspack.config.js in project root and replace the original configuration as below:

rspack.config.js
1// rspack.config.js
2// new rspack config
3const { composePlugins, withNx, withReact } = require('@nx/rspack');
4
5const rspack = require('@rspack/core');
6const refreshPlugin = require('@rspack/plugin-react-refresh');
7const { withZephyr } = require('zephyr-webpack-plugin');
8const {
9  ModuleFederationPlugin,
10} = require('@module-federation/enhanced/rspack');
11
12const isDev = process.env.NODE_ENV === 'development';
13
14/**
15 * @type {import('@rspack/cli').Configuration}
16 */
17const config = composePlugins(withNx(), withReact(), (config) => {
18  if (
19    !config.plugins ||
20    !Array.isArray(config.plugins) ||
21    !config.plugins.length
22  ) {
23    config.plugins = [];
24  }
25
26  config.plugins.push(
27    ...[
28      new ModuleFederationPlugin({
29        name: 'nx_rspack_react_mf_zephyr',
30        filename: 'remoteEntry.js',
31        exposes: {},
32        shared: {
33          react: { eager: true },
34          'react-dom': { eager: true },
35          'react-router-dom': { eager: true },
36        },
37      }),
38      new rspack.DefinePlugin({
39        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
40      }),
41      new rspack.ProgressPlugin({}),
42      new rspack.HtmlRspackPlugin({
43        template: './src/index.html',
44      }),
45      isDev ? new refreshPlugin() : null,
46    ].filter(Boolean)
47  );
48
49  return withZephyr()(config);
50});
51
52module.exports = config;

Now you are all set! Go back to the terminal in current project and run

Terminal
1nx build

You will see the terminal output like so - your deployed URL is before the final emitting process:

Terminal
1❯ nx build
2
3 NX   Its time to update Nx 🎉
4
5Your repository uses a higher version of Nx (19.2.2) than your global CLI version (18.1.2)
6For more information, see https://nx.dev/more-concepts/global-nx
7
8
9> nx run my-first-mf-app:build:production
10
11[zephyr] You are already logged in
12●  ━━━━━━━━━━━━━━━━━━━━━━━━━ (70%) sealing chunk ids                                                                                                    
13[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: uploading missing assets to zephyr (queued 1 out of 2)
14[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: uploaded local snapshot in 263ms
15[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: uploaded missing assets to zephyr (1 assets in 144ms, 236.95kb)
16[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: deploying to https://userName_69-_my-first-mf-app_source-my-f-53eac2-ze.valorkin.dev
17[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: deploying to https://userName_70-_my-first-mf-app_source-my-f-38438b-ze.valorkin.dev
18[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: deploying to https://_my-first-mf-app_source-my-first-mf-app-username-ze.valorkin.dev
19●  ━━━━━━━━━━━━━━━━━━━━━━━━━ (98%) emitting emit                                                                                                        
20[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[70]: build deployed in 774ms
21●  ━━━━━━━━━━━━━━━━━━━━━━━━━ (100%) emitting after emit                                                                                                 
22PublicPath: auto
23asset index.html 362 bytes [emitted]
24asset main.js 237 KiB [emitted] (name: main)
25Entrypoint main 237 KiB = main.js
26runtime modules 6 modules
27+ 24 modules
28Rspack 0.6.5 compiled successfully in 1.35 s (036ed42385758a40269f)
29
30———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
31
32 NX   Successfully ran target build for project my-first-mf-app (2s)

Press

Command
and left click on the URL at the same time to open your deployed URL in your default browser. Meanwhile open your side panel by clicking on . Note that this URL is alive as long you don't delete your account and you can share it with anyone to preview it.

Every application you have deployed on Zephyr (under the same account) will be displayed under Name, categorized by repository name and their package name. Click on the dropdown menu under Version you will only the initial version of your app.

5. Deploy a new version

Now you have deployed the first version, let's add modify the app and deploy a new version. Open the file src/app/app.tsx and change the content of your home page:

src/app/app.tsx
1import NxWelcome from './nx-welcome'; // [!code --]
2
3export function App() { 
4  return ( 
5    <div> // [!code --]
6      <NxWelcome title="my-first-mf-app" /> // [!code --]
7    </div> // [!code --]
8    <div className="min-w-screen h-screen flex items-center justify-center bg-black "> // [!code ++]
9      <a // [!code ++]
10        href="https://zephyr-cloud.io" // [!code ++]
11        target="_blank" // [!code ++]
12        rel="noreferrer" // [!code ++]
13        className="py-8 px-8 absolute bg-gradient-to-r z-20 w-[400px] flex justify-center rounded-lg from-[#111830] via-sky-950 to-teal-950" // [!code ++]
14      > // [!code ++]
15        <p className="text-white z-10 text-xl font-semibold tracking-wide"> // [!code ++]
16          My First App deployed to Zephyr! // [!code ++]
17        </p>{' '} // [!code ++]
18      </a> // [!code ++]
19    </div> // [!code ++]
20  ); 
21} 
22
23export default App;

If the styling is acting weird let's do a quick fix by serving Tailwind from CDN.

src/index.html
1<!DOCTYPE html>
2<html lang="en">
3
4<head>
5  <meta charset="utf-8" />
6  <title>MyFirstMfApp</title>
7  <base href="/" />
8  <script src="https://cdn.tailwindcss.com"></script> // [!code ++]
9  <meta name="viewport" content="width=device-width, initial-scale=1" />
10  <link rel="icon" type="image/x-icon" href="favicon.ico" />
11</head>
12
13<body>
14  <div id="root"></div>
15</body>
16
17</html>

If you run a nx serve you will see your app changed to:

Save the file and go back to the terminal to deploy the new version of your application - run:

Terminal
1nx build

You will see the new version of your app both in the console output and under Version dropdown in on Chrome Extension.

Terminal
1❯ nx build
2
3 NX   Its time to update Nx 🎉
4
5Your repository uses a higher version of Nx (19.2.2) than your global CLI version (18.1.2)
6For more information, see https://nx.dev/more-concepts/global-nx
7
8
9> nx run my-first-mf-app:build:production
10
11[zephyr] You are logged in
12●  ━━━━━━━━━━━━━━━━━━━━━━━━━ (62%) building builtin:swc-loader??ruleSet[1].rules[2].use[0]!/username/my-first-mf-app/node_modules/scheduler/
13[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: uploading missing assets to zephyr (queued 2 out of 2)
14[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: uploaded local snapshot in 217ms
15[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: uploaded missing assets to zephyr (2 assets in 342ms, 212.50kb)
16[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: deploying to https://account_71-_my-first-mf-app_source-my-f-4b579f-ze.valorkin.dev
17[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: deploying to https://account_70-_my-first-mf-app_source-my-f-38438b-ze.valorkin.dev
18[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: deploying to https://_my-first-mf-app_source-my-first-mf-app-username-ze.valorkin.dev
19●  ━━━━━━━━━━━━━━━━━━━━━━━━━ (98%) emitting emit                                                                                                               
20[zephyr]: [_my-first-mf-app_source.my-first-mf-app.username](account)[71]: build deployed in 1033ms
21●  ━━━━━━━━━━━━━━━━━━━━━━━━━ (100%) emitting after emit                                                                                                        
22PublicPath: auto
23asset index.html 398 bytes [emitted]
24asset main.js 212 KiB [emitted] (name: main)
25Entrypoint main 212 KiB = main.js
26runtime modules 6 modules
27+ 23 modules
28Rspack 0.6.5 compiled successfully in 5.60 s (ecb32c555d4d1978eae7)
29
30—————————————————————————————————————————————————————————————————————————————————
31
32NX   Successfully ran target build for project my-first-mf-app (6s)

Now the latest version of your app is deployed. You can check the source code till this stage here:

Version name

The names of your versions are generated by Zephyr. The first part of the name is the branch name, serialised version of your email, followed by the version number.

6. Rollback to previous version

The first option in the dropdown menu under Version is the latest deployment of your app. In the dropdown menu you will see more previous version of your app.

But if you want to rollback to the previous version of your deployed application, you can click on one of the options and that version will show up in the browser, once you confirm that you want to push it to production you can click on Publish updates at the bottom of the side panel.

6. Chrome Extension

You can check the application you just deployed in our chrome extension.

Head to Chrome Web Store to install our chrome extension - Zephyr Mission Control. Click on Add to Chrome and confirm with Add extension. After you finish remember to pin the extension by clicking on on extension management tab to provide you a quicker access to Zephyr's side panel.

Once you click on the side panel will pop up and prompt you to log in (if you are using Microsoft Edge you will need to click on Open Side Panel).

What happens when you log in?

While we are loggin you in, we are storing your authorization information locally under ~/.zephyr in your root directly. Whenever you want to clean up your local profile information (they are JWT claims for each of the project you deployed through Zephyr), you can enter your root directory in terminal and run:

1rm rf ~/.zephyr

Now you have created an account and the side panel is empty - hold up! We will get into how to use our dashboard in a bit. Let's deploy an app through Zephyr so you can see a live example of how to use our side panel.

INFO

Our chrome extension is only supported on Chromium based browsers. See a list of supported browser.

7. Dashboard

If you want to see all your projects and their versions, sign in on dashboard and you will see all your projects and their dependencies.

A more detailed explaination on how to use our dashboard is coming soon.