This is an example of using Nx's project and file graphs to make configuring module federation easier.
The goals are:
- Start host and remotes in a single command.
- Reduce boilerplate in
vite.config.ts
by using what Nx understands about our files and projects.
For (2), the configuration shouldn't need to provide shared
for example, since Nx already knows what dependencies are being used by all the projects.
// ..
import { nxFederation } from '../nx-federation-plugin';
export default defineConfig({
plugins: [
react(),
nxFederation({
name: 'host',
// no need to define full URL to remoteEntry.js since Nx can find the project by name and read the host+port.
remotes: ['remote']
// shared is missing but Nx will fill it in as ['react', 'react-dom', ...]
}),
nxViteTsPaths()
],
// ...
});
Since there isn't an official module federation plugin, we're using the @originjs/vite-plugin-federation
. This is the most widely used solution, and the most stable.
Try it yourself!
npx nx run-many -t=serve --projects=host,remote
The above command will start the host at http://localhost:3000, and the remote at http://localhost:3001. The host app uses react-router-dom
to provide the home (/
) and remote (/remote
) routes. Navigating to /remote
will load the federated remote app.
The following is a quick explanation of the files in this repo. Check out the host/vite.config.ts
and remote/vite.config.ts
to see how nxFederation
is used.
.
|-- host <- the host app that uses react-router-dom
| |-- src
| | |-- app
| | | |-- app.module.css
| | | `-- app.tsx <- app component
| | |-- assets
| | |-- main.tsx <- main entry
| | `-- styles.css
| |-- ...
| `-- vite.config.ts <- uses custom nxFederation plugin
|-- nx-federation-plugin <- this is a wrapper around nx and @originjs/vite-plugin-federation
| |-- src
| | `-- index.ts <- implementation
| |-- ...
| `-- tsconfig.spec.json
|-- remote <- the remote app that exposes `remote/Module` as a page component
| |-- src
| | |-- app
| | | |-- app.module.css
| | | `-- app.tsx
| | |-- assets
| | |-- main.tsx
| | |-- remote-entry.ts <- what `remote/Module` points to
| | `-- styles.css
| |-- ...
| `-- vite.config.ts <- uses custom nxFederation plugin
|-- ...
`-- tsconfig.base.json
- Nx can automatically pick up shared dependencies so
shared
does not need to be define manually. - Nx understands the projects in the repo, so we can link to a remote by name rather than manually configuring the full URL to
remoteEntry.js
. - Nx task orchestration makes serving and build easier. Since remote has to run in preview mode (see painpoints), we can easily wire up
build --watch
at the same time.
Note: You can easily do away with nx-federation-plugin
and manually configure @originjs/vite-plugin-federation
by hand. You will some of the benefits of using Nx, but the tasks defined in project.json
files are still useful.
- No Nx plugin to support Vite module federation, so we have to roll our own.
- One of the utils used is from
@nx/webpack
, which isn't ideal. Maybe it should be inlined here. - Remotes do not generate
remoteEntry.js
unless running in preview mode. This is a known issue - Cannot import our plugin as
@acme/nx-federation-plugin
sincevite.config.ts
does not understand tsconfig paths.