Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 2 additions & 13 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,10 @@ name: Bug Report
description: Report a bug or regression in functionality

body:
- type: dropdown
id: affected-packages
attributes:
label: With what library do you have an issue?
options:
- native-federation
- module-federation
validations:
required: true

- type: textarea
id: reproduction
attributes:
label: Reproduction of the bug/regression with instructions
description: If on Native Federation, use our [Stackblitz template](https://stackblitz.com/github/rainerhahnekamp/native-federation-stackblitz?file=projects%2Fhost%2Fsrc%2Fapp%2Fapp.routes.ts) to reproduce the issue
placeholder: If the bug/regression does not include a reproduction via StackBlitz or GitHub repo, your issue may be closed without resolution.
validations:
required: true
Expand All @@ -32,9 +21,9 @@ body:
- type: textarea
id: version
attributes:
label: Versions of Native/Module Federation, Angular, Node, Browser, and operating system
label: Versions of Module Federation, Angular, Node, Browser, and operating system
placeholder: |
Native/Module Federation:
Module Federation:
Angular:
Node:
Browser:
Expand Down
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/feature-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ body:
attributes:
label: For which library do you have a feature request?
options:
- native-federation
- module-federation
- other
multiple: true
Expand Down
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/question.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ body:
attributes:
label: For which library do you need help?
options:
- native-federation
- module-federation
- other
multiple: true
Expand Down
12 changes: 1 addition & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,7 @@ jobs:
cache: 'npm'
- run: npm ci

# Install Playwright browsers
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
timeout-minutes: 10
env:
DEBIAN_FRONTEND: noninteractive
NEEDRESTART_MODE: a
NEEDRESTART_SUSPEND: '1'

- uses: nrwl/nx-set-shas@v4

- run: npx nx format:check
#TODO: remove exclude when apps are fixed
- run: npx nx affected -t lint test build --exclude mfe1 mfe2 playground
- run: npx nx affected -t lint test build
72 changes: 26 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
# @angular-architects/module-federation

- [Readme for Module Federation](./libs/mf/README.md)
- [Readme for Native Federation](./libs/native-federation/README.md)

> [!WARNING]
> **Native federation has moved!**
> [!IMPORTANT]
> **Native Federation has moved to its own organization: [github.com/native-federation](https://github.com/native-federation).**
>
> This is our older deprecated v3 version. Starting Angular 22, we're moving to a new repository. For upgrading from v3 to v4, please have a look at our [new repository](https://github.com/native-federation/angular-adapter).

## Local Development

<details>
<summary>Playground App</summary>

You can test directly the libraries by using the playground application:

1. Start the `host` application:
```shell
npx nx run playground:serve
```
2. Start the `remote` application:
```shell
npx nx run mfe1:serve --port 3001
```
> This repository now only hosts the Module Federation packages. If you are looking for Native
> Federation, or want to upgrade from v3 to v4, head to
> [native-federation/angular-adapter](https://github.com/native-federation/angular-adapter).
>
> The deprecated Native Federation v3 sources for Angular 21 remain available on the
> [`21.x.x`](https://github.com/angular-architects/module-federation-plugin/tree/21.x.x) backport
> branch.

By using that approach you can test your modifications on the libraries.
- [Readme for Module Federation](./libs/mf/README.md)
- [Migration guides](./migration-guide.md)
- [Webpack Module Federation demo](./apps/README.md) — a host and two remotes
running against the sources in `libs/`

</details>
## Local Development

<details>
<summary>Test Library on external repository</summary>
Expand All @@ -39,24 +29,18 @@ If you want to test the modifications directly on your application, you can foll
```
2. Then you can publish the libraries by using:

- For Module federation:
```shell
npm run publish-local:mf
```
- For Native federation:

```shell
npm run publish-local:nf
```
```shell
npm run publish-local
```

This will first `build` the libraries and `publish` them to [http://localhost:4873](http://localhost:4873)
This will first `build` the libraries and `publish` them to [http://localhost:4873](http://localhost:4873)

3. Then just re-run the `install` on the other repo with you favorite package manager.

By default, the version from the `package.json` will be used. However, you can provide the version for a specific library by using:

```shell
npx nx run native-federation:publish-local -- --ver=17.0.8
npx nx run mf:publish-local -- --ver=22.0.1
```

</details>
Expand All @@ -65,20 +49,16 @@ npx nx run native-federation:publish-local -- --ver=17.0.8

Follow these steps to publish all libraries on `npm`:

- For Module federation:
```shell
npm run publish:mf
```
- For Native federation:
```shell
npm run publish:nf
```
This will first `build` the libraries and `publish` them to `npm registry`.
```shell
npm run publish
```

This will first `build` the libraries and `publish` them to `npm registry`.

By default, the version from the `package.json` will be used and the tag will be `next`. However, you can provide the version and the tag for a specific library by using:
By default, the version from the `package.json` will be used and the tag will be `latest`. However, you can provide the version and the tag for a specific library by using:

```shell
npx nx run native-federation:publish -- --ver=17.0.8 --tag=latest
npx nx run mf:publish -- --ver=22.0.1 --tag=latest
```

</details>
99 changes: 99 additions & 0 deletions apps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Webpack Module Federation demo

A dynamic host and two remotes, built against the sources in `libs/`. Useful as a
manual smoke test for `@angular-architects/module-federation` and as a worked
example of the config the `init-webpack` schematic generates.

| Project | Port | Role | Exposes |
| ------- | ---- | ------------ | ------------------------------------ |
| `shell` | 4200 | Dynamic host | — |
| `mfe1` | 4201 | Remote | `./routes` → `FLIGHT_ROUTES` |
| `mfe2` | 4202 | Remote | `./Component` → `DashboardComponent` |

`libs/playground-lib` is shared by all three as a singleton, via `sharedMappings`.

## Run it

```shell
npx nx serve shell
```

`shell:serve` depends on both remotes' `serve` targets, so one command starts all
three. Then open <http://localhost:4200>, type a name into the login box, and
open _Flights_ and _Dashboard_: both are separate builds served from other ports,
and both read the name back out of the same `AuthService` instance.

Each app also runs on its own — <http://localhost:4201> and
<http://localhost:4202> are complete Angular apps.

To build instead:

```shell
npx nx run-many -t build -p shell mfe1 mfe2
```

## What each piece demonstrates

**Dynamic host.** `shell/webpack.config.js` declares no `remotes`. The shell
learns about mfe1 and mfe2 at runtime from `shell/public/mf.manifest.json`, which
`initFederation()` in `shell/src/main.ts` fetches before Angular boots. Remotes
can move or be added without rebuilding the shell — edit the manifest in
`dist/apps/shell/` and reload.

**Async boundary.** Every app's `main.ts` only does `import('./bootstrap')`.
Nothing may touch a shared library before the share scope is initialized, so all
real work sits behind a dynamic import.

**Two granularities of exposure.** mfe1 exposes routes and owns everything under
`/flights`; mfe2 exposes a single component that the shell routes to itself. See
`shell/src/app/app.routes.ts` for both call shapes of `loadRemoteModule`.

**Sharing.** `shareAll({ singleton: true, strictVersion: true, requiredVersion:
'auto' })` shares every runtime dependency in the root `package.json`.
`requiredVersion: 'auto'` reads the version from that same `package.json`, so all
three builds agree. In the network tab, `remoteEntry.js` comes from `:4201` and
`:4202`, but `@angular/core` is downloaded once — from whichever build asks
first.

**Monorepo libraries.** `libs/playground-lib` has no version of its own, so
`shareAll` cannot see it. `sharedMappings: ['@angular-architects/playground-lib']`
resolves it through `tsconfig.base.json` `paths` and shares it with
`requiredVersion: false`. That is what makes `AuthService` a true singleton across
build boundaries.

## Deviations from a normal app

These exist only because the demo lives inside the plugin's own repository:

- The `webpack.config.js` files require `../../dist/libs/mf/webpack` instead of
`@angular-architects/module-federation/webpack`, because the package is never
installed here. Both the `build` and `serve` targets `dependsOn` `mf:build` so
the output exists before webpack loads the config.
- `shell/webpack.config.js` adds two `resolve.alias` entries for
`@angular-architects/module-federation` and `-runtime`. Angular's webpack build
ignores tsconfig `paths`, so the aliases mirror the two entries the shell
relies on. They point at `libs/*/src`, **not** `dist/` — building `mf` also
rebuilds `mf-runtime`, and ng-packagr recreates `dist/libs/mf-runtime`, which
would yank the module out from under a dev-server already watching it. Using
sources also means editing a library live-reloads the demo.
- `shell/tsconfig.app.json` sets `strict: false`. `libs/mf-runtime` is itself
compiled with `strict: false` and violates `strictNullChecks` and
`noImplicitAny`, and a strict program cannot consume those sources. Only the
app build is relaxed; the specs still type-check strictly. `mfe1` and `mfe2`
don't import the runtime, so they stay fully strict.

Everything else is what `ng g @angular-architects/module-federation:init-webpack`
generates for an Nx workspace: the `@nx/angular:webpack-browser` and
`@nx/angular:dev-server` builders, `commonChunk: false`,
`extractLicenses: false`, and a CORS header on each remote's dev-server.

## Known cosmetic error (dev builds only)

Under `nx serve`, every page load logs `SyntaxError: Cannot use 'import.meta'
outside a module`. `withModuleFederationPlugin` sets `experiments.outputModule`,
so webpack emits ESM for _all_ entry points, but Angular's index-html generator
injects the `styles` entry with `defer` rather than `type="module"`. The failing
chunk holds only webpack's runtime boilerplate — global CSS is applied through
the separate `<link rel="stylesheet" href="styles.css">`, and nothing else is
affected. Production builds don't emit a `styles` script at all, so they are
clean.
12 changes: 0 additions & 12 deletions apps/mfe1-e2e/cypress.json

This file was deleted.

17 changes: 0 additions & 17 deletions apps/mfe1-e2e/eslint.config.mjs

This file was deleted.

30 changes: 0 additions & 30 deletions apps/mfe1-e2e/project.json

This file was deleted.

4 changes: 0 additions & 4 deletions apps/mfe1-e2e/src/fixtures/example.json

This file was deleted.

13 changes: 0 additions & 13 deletions apps/mfe1-e2e/src/integration/app.spec.ts

This file was deleted.

22 changes: 0 additions & 22 deletions apps/mfe1-e2e/src/plugins/index.js

This file was deleted.

1 change: 0 additions & 1 deletion apps/mfe1-e2e/src/support/app.po.ts

This file was deleted.

Loading
Loading