At this stage, select 'None' for the frontend framework to keep the setup minimal.
Terminal
NX Let's create a new workspace [https://nx.dev/getting-started/intro]? Which stack do you want to use? …
None: Configures a TypeScript/JavaScript project with minimal structure.
React: Configures a React application with your framework of choice.
Vue: Configures a Vue application with your framework of choice.
Angular: Configures a Angular application with modern tooling.
Node: Configures a Node API application with your framework of choice.
We opt for the Integrated configuration as it allows us to house all remotes and the shell within a single repository:
Terminal
? Package-based monorepo, integrated monorepo, or standalone project? …
Package-based Monorepo: Nx makes it fast, but lets you run things your way.
Integrated Monorepo: Nx creates a monorepo that contains multiple projects.
Standalone: Nx creates a single project and makes it fast.
While any Nx Cloud setup option is valid, "Skipping for Now" is chosen in our example, though activating Nx Cloud can significantly enhance local and CI build speeds:
Terminal
? Do you want Nx Cloud to make your CI fast? …
(it's free and can be disabled any time)Yes, enable Nx Cloud
Yes, configure Nx Cloud for GitHub Actions
Yes, configure Nx Cloud for Circle CI
Skip for now
At this stage, we will use Nx to integrate React support. While our example specifically uses React, you may choose to use a different framework according to your project needs:
When prompted, choose your preferred stylesheet format. Options include CSS, SASS, LESS, and others:
Terminal
? Which stylesheet format would you like to use? …
CSS
SASS(.scss)[ https://sass-lang.com ]LESS [ https://lesscss.org ]tailwind [ https://tailwindcss.com/ ]styled-components [ https://styled-components.com ]emotion [ https://emotion.sh ]styled-jsx [ https://www.npmjs.com/package/styled-jsx ]None
Select "As Provided" for project names, as no adjustments are necessary:
Terminal
? What should be the project name and where should it be generated? …
❯ As provided:
Name: shell
Root: apps/shell
Derived:
Name: shell-shell
Root: apps/shell/shell
Zephyr Cloud requires a package.json file in each application to resolve names. Create a package.json for each application, specifying a unique name for each:
Update both the webpack.config.ts and webpack.config.prod.ts files for shell and webpack.config.ts for both remotes.
INFO
Rspackis also supported however this example uses Webpack
shell/webpack.config.ts
import{ composePlugins, withNx, ModuleFederationConfig }from'@nx/webpack';import{ withReact }from'@nx/react';import{ withModuleFederation }from'@nx/react/module-federation';import baseConfig from'./module-federation.config';import{ withZephyr }from'zephyr-webpack-plugin';const config: ModuleFederationConfig ={...baseConfig,};// Nx plugins for webpack to build config object from Nx options and context.exportdefaultcomposePlugins(withNx(),withReact(),withModuleFederation(config),withZephyr(),(config)=>{return config;});
shell/webpack.config.prod.ts
import{ composePlugins, withNx }from'@nx/webpack';import{ withReact }from'@nx/react';import{ withModuleFederation }from'@nx/react/module-federation';import{ ModuleFederationConfig }from'@nx/webpack';import baseConfig from'./module-federation.config';import{ withZephyr }from'zephyr-webpack-plugin';const prodConfig: ModuleFederationConfig ={...baseConfig,/*
* Remote overrides for production.
* Each entry is a pair of a unique name and the URL where it is deployed.
*
* e.g.
* remotes: [
* ['app1', 'http://app1.example.com'],
* ['app2', 'http://app2.example.com'],
* ]
*
* You can also use a full path to the remoteEntry.js file if desired.
*
* remotes: [
* ['app1', 'http://example.com/path/to/app1/remoteEntry.js'],
* ['app2', 'http://example.com/path/to/app2/remoteEntry.js'],
* ]
*/ remotes:[['remote1','http://localhost:4201/'],['remote2','http://localhost:4202/'],],};// Nx plugins for webpack to build config object from Nx options and context.exportdefaultcomposePlugins(withNx(),withReact(),withModuleFederation(prodConfig),withZephyr(),(config)=>{return config;});
remote1/webpack.config.ts
import{ composePlugins, withNx }from'@nx/webpack';import{ withReact }from'@nx/react';import{ withModuleFederation }from'@nx/react/module-federation';import baseConfig from'./module-federation.config';import{ withZephyr }from'zephyr-webpack-plugin';const config ={...baseConfig,};// Nx plugins for webpack to build config object from Nx options and context.exportdefaultcomposePlugins(withNx(),withReact(),withModuleFederation(config),withZephyr(),(config)=>{return config;});
remote2/webpack.config.prod.ts
import{ composePlugins, withNx }from'@nx/webpack';import{ withReact }from'@nx/react';import{ withModuleFederation }from'@nx/react/module-federation';import baseConfig from'./module-federation.config';import{ withZephyr }from'zephyr-webpack-plugin';const config ={...baseConfig,};// Nx plugins for webpack to build config object from Nx options and context.exportdefaultcomposePlugins(withNx(),withReact(),withModuleFederation(config),withZephyr(),(config)=>{return config;});
To build the shell application, execute the following command, which uses watch mode for ongoing updates:
Terminal
npx nx build shell -- --watch
INFO
Ensure you have created package.json files in each project directory as outlined earlier. Failure to do so may result in errors like the ones below, indicating unresolved remote entry points:
[zephyr] Could not resolve 'remote1.zephyr-examples.zephyrcloudio' with version 'http://localhost:4201/remoteEntry.js'[zephyr] Could not resolve 'remote2.zephyr-examples.zephyrcloudio' with version 'http://localhost:4202/remoteEntry.js'
nx run shell:build:production --watch
✔ You are already logged in[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: local build started
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: started uploading of local snapshot to zephyr
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: uploaded local snapshot in 805ms
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: uploading missing assets to zephyr (queued 11 out of 14)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file main.93e9078aa7b6c830.js uploaded in 126ms (8.31kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file913.026a13b340471b7f.js.LICENSE.txt uploaded in 139ms (0.66kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file943.a0a6b971d9115018.js uploaded in 150ms (27.19kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file41.b26ddec4260a2e36.js uploaded in 156ms (6.43kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file index.html uploaded in 150ms (0.48kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file144.3652843fc7a12189.js.LICENSE.txt uploaded in 158ms (0.47kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file41.b26ddec4260a2e36.js.LICENSE.txt uploaded in 160ms (0.23kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file styles.ecbc7c8fef0c436e.js uploaded in 169ms (5.84kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file943.a0a6b971d9115018.js.LICENSE.txt uploaded in 174ms (0.24kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file913.026a13b340471b7f.js uploaded in 217ms (63.79kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: file144.3652843fc7a12189.js uploaded in 222ms (129.66kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: uploaded missing assets to zephyr (11 assets in 1821ms, 243.31kb)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: started deploying local build to edge
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: deployed to https://valorkin_3016-shell-zephyr-examples-zephyrcloudio-ze.valorkin.dev
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: deployed to https://t_main_zack_zephyr-cloud_io-pe4ufnqhxd-shell-zephyr-e-80bb4d-ze.valorkin.dev
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: deployed to https://shell-zephyr-examples-zephyrcloudio-ze.valorkin.dev
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: local build deployed to edge in 188ms
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: build deployed in 1634ms
Entrypoint main 8.31 KiB = main.93e9078aa7b6c830.js
Entrypoint styles 5.92 KiB = styles.5f4524c1fa820eae.css 81 bytes styles.ecbc7c8fef0c436e.js 5.84 KiB
chunk (runtime: main, styles)41.b26ddec4260a2e36.js 6.94 KiB [rendered]chunk (runtime: main, styles)144.3652843fc7a12189.js (id hint: vendors)134 KiB [rendered] reused as split chunk (cache group: defaultVendors)chunk (runtime: main, styles)42 bytes reused as split chunk (cache group: default)chunk (runtime: main)6 bytes (remote)6 bytes (share-init)chunk (runtime: main)42 bytes
chunk (runtime: main)42 bytes
chunk (runtime: main) main.93e9078aa7b6c830.js (main)139 bytes (javascript)126 bytes (share-init)21.1 KiB (runtime)[entry][rendered]chunk (runtime: main)6 bytes (remote)6 bytes (share-init)chunk (runtime: styles) styles.5f4524c1fa820eae.css, styles.ecbc7c8fef0c436e.js (styles)50 bytes (javascript)80 bytes (css/mini-extract)126 bytes (share-init)19 KiB (runtime)[entry][rendered]chunk (runtime: main, styles)913.026a13b340471b7f.js (id hint: vendors)228 KiB [rendered] reused as split chunk (cache group: defaultVendors)chunk (runtime: main)943.a0a6b971d9115018.js 37.4 KiB (javascript)84 bytes (consume-shared)[rendered]webpack compiled successfully (533e09796edd0232)[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: local build finished in 3265ms
INFO
The build process generates a series of URLs for each deployment. For a comprehensive understanding of these build outputs, please consult our versioning documentation.
Terminal
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: deployed to https://valorkin_3016-shell-zephyr-examples-zephyrcloudio-ze.valorkin.dev
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: deployed to https://t_main_zack_zephyr-cloud_io-pe4ufnqhxd-shell-zephyr-e-80bb4d-ze.valorkin.dev
[shell.zephyr-examples.zephyrcloudio](valorkin)[3016]: deployed to https://shell-zephyr-examples-zephyrcloudio-ze.valorkin.dev