Skip to content

Conversation

@chintankavathia
Copy link
Member

@chintankavathia chintankavathia commented Jan 8, 2026

Existing module federation remains unchanged.

Additionally there are now two other entry point options introduced:

Host App on native federation and all remote apps using native federation

  • registerNativeFederatedWidgetLoader shall be used from @siemens/dashboards-ng/native-federation

Host app on native federation and some remote apps using module federation and some native federation

  • use registerModuleFederatedWidgetLoader from @siemens/dashboards-ng/native-federation/mf-bridge

Demo:

To run demo with native federation

npm run dashboards-demo:start:esm (starts host app)
npm run dashboards-demo:start:mfe:esm (starts remote app in native federation configuration)
npm run dashboards-demo:start:mfe (startes remote app in module federation configuration)

Build

Build pipeline is updated to also build dashboards-demo with native federation configuration
Artifacts will be generated under dashboards-demo-esm

E2E

Playwirght config is updated to run dashboards e2e in module federation as well as native federation environment

Setup motivation

https://www.angulararchitects.io/blog/combining-native-federation-and-module-federation/

Illustration

image

Summary

This PR adds native federation support to @siemens/dashboards-ng, enabling applications to leverage native ES modules for federation alongside existing module federation capabilities.

Key Features

New Public APIs:

  • registerNativeFederatedWidgetLoader() – Registers widget loading for pure native federation setups across host and remotes
  • registerModuleFederatedWidgetLoader(mfInstance) – Bridges native federation hosts with module federation remotes

Widget Configuration:

  • Extended FederatedModule type to support 'native-federation' factory type
  • Introduced FederatedBridgeModule and LoadRemoteBridgeOptions types for hybrid federation scenarios
  • Added conditional widget configuration based on useModuleFederation environment flag

Build & Development

New NPM Scripts:

  • dashboards-demo:start:esm / dashboards-demo:start:esm:prod – Start host in native federation mode
  • dashboards-demo:start:mfe:esm – Start remote in native federation mode
  • dashboards-demo:build:esm / dashboards-demo:build:esm:mfe / dashboards-demo:build:bridge:mfe – Build variants

Angular Configuration:

  • Added esbuild-based build targets with native federation support (@angular-architects/native-federation builder)
  • Created federation.config.js for both host and remote MFE with shared dependency configuration

Environment Management:

  • Added .esm.ts and .esm.prod.ts environment files configuring federation base URLs and feature flags
  • Updated main entry point (main.ts) with dual-path initialization supporting both federation modes

Testing

  • Updated Playwright configuration to run dashboards E2E tests against both module federation and native federation environments
  • Added new dashboards-demo-esm projects with corresponding visual regression snapshots

Dependencies

Added: @angular-architects/native-federation, @module-federation/enhanced, @softarc/native-federation-node, es-module-shims

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 5 times, most recently from 24d0951 to 0da8542 Compare January 9, 2026 11:07
@chintankavathia chintankavathia marked this pull request as ready for review January 9, 2026 11:26
@chintankavathia chintankavathia requested a review from a team as a code owner January 9, 2026 11:26
@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

📝 Walkthrough

Walkthrough

This PR introduces Native Federation (ESM-based module federation) as an alternative to the existing Webpack-based Module Federation approach. It adds new ESM build targets across multiple projects, introduces native-federation configuration files, creates widget loader registries for both native-federation and mf-bridge federation types, adds environment-specific configurations for ESM builds, and modifies the bootstrap flow to conditionally initialize either Module Federation or Native Federation based on environment configuration. The changes include new federation.config.js files, environment files, build configurations in angular.json, and integration of @angular-architects/native-federation and @module-federation/enhanced dependencies.

Sequence Diagram(s)

sequenceDiagram
    participant App as App Bootstrap
    participant Env as Environment Config
    participant NF as Native Federation Init
    participant MF as Module Federation Instance
    participant WL as Widget Loader Registry
    participant RW as Remote Widget

    App->>Env: Check useModuleFederation
    
    alt useModuleFederation = true (Module Federation Path)
        App->>WL: Load module-federation package
        App->>WL: Register widget loader
        App->>App: Bootstrap with appConfig
    else useModuleFederation = false (Native Federation Path)
        App->>NF: Call initFederation()
        NF-->>App: Federation initialized
        App->>NF: Get shared config
        App->>MF: Create ModuleFederation instance
        MF-->>App: mfInstance ready
        App->>WL: Load native-federation package
        App->>WL: Load mf-bridge package
        App->>WL: Register native-federation loader
        App->>WL: Register mf-bridge loader
        App->>App: Bootstrap with appConfig
    end
    
    App->>RW: Load remote widget via factory
    RW-->>App: Widget component loaded
Loading
sequenceDiagram
    participant WF as Widget Factory
    participant NL as Native Federation Loader
    participant NF as Native Federation Runtime
    participant RM as Remote Module
    participant VCR as View Container Ref

    WF->>NL: setupRemoteComponent(config)
    NL->>NF: loadRemoteModule(config)
    NF->>RM: Fetch remote module
    RM-->>NF: Module loaded
    NF-->>NL: Module content
    NL->>NL: Resolve component type
    NL->>VCR: Create component instance
    VCR-->>NL: ComponentRef<T>
    NL-->>WF: Observable<ComponentRef<T>>
Loading

Possibly related PRs

Suggested labels

enhancement

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(dashboards-ng): support native federation' directly and clearly summarizes the main objective of the PR, which is adding native federation support to the dashboards-ng library.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
projects/dashboards-demo/tsconfig.app.prod.json (1)

4-11: Fix type-whitelist inconsistency in prod tsconfig: restore localize-types.

The types: ["node"] override removes @siemens/element-translate-ng/localize-types, creating an inconsistency with the non-prod variant (tsconfig.app.json) which includes both. Since the codebase uses @siemens/element-translate-ng modules (e.g., provideNgxTranslateForElement, SiTranslatePipe), the prod config should match the non-prod setup to avoid type-checking failures.

Recommended fix
   "compilerOptions": {
     "outDir": "../../out-tsc/app",
-    "types": ["node"]
+    "types": ["@siemens/element-translate-ng/localize-types", "node"]
   },
🤖 Fix all issues with AI agents
In @.github/workflows/build-and-test.yaml:
- Around line 44-50: Update the two CI steps that run the ESM dashboard builds
to add the --progress=false flag for consistency: modify the run steps that
invoke "npm run dashboards-demo:build:esm" and "npm run
dashboards-demo:build:esm:mfe" so they include "-- --progress=false" like the
other dashboard build steps, ensuring quieter logs and consistent behavior
across builds.

In @playwright/e2e/dashboards-demo/dashboard.spec.ts:
- Around line 37-38: The detection of ESM build via
test.info().project.name.includes('esm') is brittle; update the logic that sets
stepName (currently using stepName = test.info().project.name.includes('esm') ?
'esm-edit' : 'edit') to read an explicit flag instead — either check a dedicated
environment variable (e.g., process.env.PLAYWRIGHT_BUILD === 'esm') or add a
custom property on the Playwright project config (e.g.,
test.info().project.metadata?.build === 'esm'), then pass that flag to determine
stepName and call si.runVisualAndA11yTests(stepName) accordingly.

In @projects/dashboards-demo/federation.config.js:
- Around line 31-32: Replace the shortened link "https://shorturl.at/jmzH0" in
the comment line "// Please read our FAQ about sharing libs:" with the full
direct URL to the FAQ documentation so the comment reads with a clear, permanent
destination (keep the existing comment text and simply swap the short URL for
the direct FAQ link).

In @projects/dashboards-demo/mfe/src/environments/environment.esm.ts:
- Around line 9-13: The exported environment object is missing the mfeEsmBaseUrl
property used by native federation; update the environment object in
environment.esm.ts (the exported "environment") to include mfeEsmBaseUrl:
'http://localhost:4205' alongside the existing mfeBaseUrl, webComponentsBaseUrl
and useModuleFederation entries so callers can safely read
environment.mfeEsmBaseUrl at runtime.

In @projects/dashboards-demo/mfe/src/main.esm.ts:
- Around line 7-9: initFederation() is being awaited only via .then(...) so
errors thrown by initFederation are not caught; change the chain to handle
failures from both initFederation and the dynamic bootstrap import by attaching
a .catch to the initFederation promise (or convert to an async IIFE with
try/catch) and log the error via console.error (or the project logger) including
context; specifically update the call site that currently calls
initFederation().then(() => { import('./bootstrap').catch(err =>
console.error(err)); }); to ensure any rejection from initFederation or from
import('./bootstrap') is caught and reported.

In @projects/dashboards-demo/mfe/tsconfig.app.json:
- Line 5: Remove the "node" entry from the tsconfig app's "types" array (i.e.,
delete "types": ["node"] or remove only the "node" element) in tsconfig.app.json
so the project no longer includes Node type definitions that conflict with
browser/DOM types; if the "types" array becomes empty you can remove the entire
"types" property.

In @projects/dashboards-demo/src/main.ts:
- Around line 40-48: The Promise.all(...).then(...) block should be converted to
async/await for consistency: await the two dynamic imports using const [m,
bridge] = await Promise.all([...]); then call
m.registerNativeFederatedWidgetLoader() and
bridge.registerModuleFederatedWidgetLoader(mfInstance) before awaiting the
dynamic bootstrap import (await import('./bootstrap')); ensure this code runs
inside an async context (or use top-level await if supported) so the awaited
operations behave the same as the original .then chain.
- Around line 8-49: Wrap the entire top-level async IIFE body in a try/catch and
add specific catches for the dynamic import and federation init steps so
failures don't silently prevent bootstrapping: catch errors from imports and
calls like import('@siemens/dashboards-ng/module-federation'), initFederation(),
createInstance(), mfInstance.initializeSharing(), Promise.all([...]).then(...),
and the final import('./bootstrap'), log a clear error (e.g., console.error or
the app logger) with the thrown error details and avoid calling
import('./bootstrap') when an upstream step failed so the app fails loudly and
predictably.
- Around line 8-14: The async IIFE currently mixes await style with .then()
chaining when loading the module federation package; change the .then() chain to
use await: inside the async IIFE, use const m = await
import('@siemens/dashboards-ng/module-federation'), call
m.registerModuleFederatedWidgetLoader() directly, and then await
import('./bootstrap') so the module loading is consistent with the rest of the
file and uses async/await throughout (references: the anonymous async IIFE,
environment.useModuleFederation,
import('@siemens/dashboards-ng/module-federation'),
registerModuleFederatedWidgetLoader, import('./bootstrap')).

In @projects/dashboards-demo/tsconfig.app.json:
- Around line 5-8: In tsconfig.app.json remove the `"node"` entry from the
"compilerOptions"."types" array (currently
["@siemens/element-translate-ng/localize-types", "node"]) so browser Angular
build does not require @types/node; update the array to only include
"@siemens/element-translate-ng/localize-types" and save the file (ensure JSON
remains valid after removal).

In @projects/dashboards-demo/webcomponents/concat.cjs:
- Line 2: The file imports the Node 'path' module into the variable path via
require('path') but never uses it; remove the unused import by deleting the var
path = require('path'); statement (or, if path is intended to be used later, use
it where needed in the relevant function), ensuring no other code references the
symbol path before removal.

In @projects/dashboards-ng/native-federation/index.ts:
- Around line 31-39: The error construction uses
JSON.stringify(rejection.toString()) which adds quotes/escaping; change it to
use the raw string instead (e.g., use rejection?.toString() or
String(rejection)) when building the message for factory.exposedModule, and pass
that to result.error followed by result.complete(); update the rejection branch
so the message is `Loading widget module ${factory.exposedModule} failed with
${rejection?.toString()}` (or String(rejection)) to keep output readable.

In @projects/dashboards-ng/native-federation/mf-bridge/index.ts:
- Around line 23-44: The promise resolution handler for loadRemote should handle
the case when module is falsy and avoid calling result.complete() after
result.error(); update the then callback that receives module (from
loadRemote<Type<T>[]>(factory.id, factory.options)) so that if module is falsy
you call result.error(...) with an informative message (e.g., include
factory.exposedModule) and return (or otherwise terminate), and remove the
subsequent result.complete() in the rejection handler (since result.error()
already terminates the Subject); ensure references are to factory,
componentName, host.createComponent, and result to locate the changes.

In @projects/dashboards-ng/src/model/widgets.model.ts:
- Around line 375-386: The JSDoc claim that LoadRemoteBridgeOptions is "Based on
`@module-federation/enhanced` loadRemote options" is misleading because the
library's loadRemote(id: string) API takes only an id; update the comment to
either remove the "Based on..." line or replace it with a clear note that
LoadRemoteBridgeOptions is a custom bridge/wrapper around the library's
loadRemote and documents the wrapper-specific fields (options.loadFactory and
options.from). Ensure the updated comment directly references the type name
LoadRemoteBridgeOptions and states that the shape diverges from
`@module-federation/enhanced`'s loadRemote API.

In @projects/dashboards-ng/tsconfig.lib.json:
- Line 7: Remove the unnecessary "node" type from the "types" array in
tsconfig.lib.json: edit the "types" entry so it only contains
"@siemens/element-translate-ng/localize-types" (remove the "node" string) to
avoid exposing Node.js globals to the browser library and align with other
libraries.
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c920c27 and 0da8542.

⛔ Files ignored due to path filters (27)
  • package-lock.json is excluded by !**/package-lock.json
  • playwright/snapshots/dashboard.spec.ts-snapshots/custom-catalog--custom-catalog-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/custom-catalog--custom-catalog-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--contact-editor-step-1-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--contact-editor-step-1-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--contact-editor-step-2-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--contact-editor-step-2-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--contact-widget-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--contact-widget-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--delete-confirmation-dialog-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--delete-confirmation-dialog-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--delete-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--delete-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--empty-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--empty-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--esm-edit-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--esm-edit-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--hello-world-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--hello-world-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--hello-world-editor-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--hello-world-editor-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--mobile-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--mobile-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--normal-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--normal-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--tablet-dashboards-demo-esm-chromium-dark-linux.png is excluded by !**/*.png
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--tablet-dashboards-demo-esm-chromium-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (40)
  • .github/workflows/build-and-test.yaml
  • .gitignore
  • angular.json
  • api-goldens/dashboards-ng/index.api.md
  • api-goldens/dashboards-ng/native-federation/index.api.md
  • api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md
  • package.json
  • playwright.config.ts
  • playwright/e2e/dashboards-demo/dashboard.spec.ts
  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--esm-edit.yaml
  • projects/dashboards-demo/eslint.config.js
  • projects/dashboards-demo/federation.config.js
  • projects/dashboards-demo/mfe/federation.config.js
  • projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts
  • projects/dashboards-demo/mfe/src/environments/environment.esm.ts
  • projects/dashboards-demo/mfe/src/environments/environment.prod.ts
  • projects/dashboards-demo/mfe/src/environments/environment.ts
  • projects/dashboards-demo/mfe/src/main.esm.ts
  • projects/dashboards-demo/mfe/src/main.ts
  • projects/dashboards-demo/mfe/tsconfig.app.json
  • projects/dashboards-demo/package.json
  • projects/dashboards-demo/src/app/widgets/module-federation-widgets.ts
  • projects/dashboards-demo/src/bootstrap.ts
  • projects/dashboards-demo/src/environments/environment.esm.prod.ts
  • projects/dashboards-demo/src/environments/environment.esm.ts
  • projects/dashboards-demo/src/environments/environment.prod.ts
  • projects/dashboards-demo/src/environments/environment.ts
  • projects/dashboards-demo/src/main.ts
  • projects/dashboards-demo/src/styles-esm.scss
  • projects/dashboards-demo/tsconfig.app.json
  • projects/dashboards-demo/tsconfig.app.prod.json
  • projects/dashboards-demo/webcomponents/concat.cjs
  • projects/dashboards-demo/webcomponents/eslint.config.js
  • projects/dashboards-demo/webpack.config.cjs
  • projects/dashboards-ng/native-federation/index.ts
  • projects/dashboards-ng/native-federation/mf-bridge/index.ts
  • projects/dashboards-ng/native-federation/mf-bridge/ng-package.json
  • projects/dashboards-ng/native-federation/ng-package.json
  • projects/dashboards-ng/src/model/widgets.model.ts
  • projects/dashboards-ng/tsconfig.lib.json
💤 Files with no reviewable changes (2)
  • projects/dashboards-demo/package.json
  • projects/dashboards-demo/src/bootstrap.ts
🧰 Additional context used
🧠 Learnings (17)
📚 Learning: 2025-12-17T04:34:55.597Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1173
File: src/app/examples/si-charts/interactive/interactive.ts:5-5
Timestamp: 2025-12-17T04:34:55.597Z
Learning: Guideline: In Angular projects using OnPush change detection (zoneless mode), you only need to call ChangeDetectorRef.markForCheck() for asynchronous operations (e.g., setTimeout, setInterval, Promises, Observables) where a change is not automatically detected. Event handlers triggered by Angular template bindings (click, input, etc.) will trigger change detection automatically and do not require explicit markForCheck() calls. Apply this broadly to TS files within Angular components/services that use OnPush; use markForCheck() selectively for async work where change detection wouldn’t run otherwise.

Applied to files:

  • projects/dashboards-demo/mfe/src/main.esm.ts
  • projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts
  • projects/dashboards-demo/src/environments/environment.esm.prod.ts
  • projects/dashboards-demo/mfe/src/environments/environment.ts
  • projects/dashboards-demo/mfe/src/environments/environment.esm.ts
  • projects/dashboards-demo/mfe/src/environments/environment.prod.ts
  • projects/dashboards-demo/src/environments/environment.esm.ts
  • projects/dashboards-ng/native-federation/index.ts
  • projects/dashboards-demo/src/environments/environment.prod.ts
  • projects/dashboards-ng/src/model/widgets.model.ts
  • projects/dashboards-demo/src/app/widgets/module-federation-widgets.ts
  • playwright/e2e/dashboards-demo/dashboard.spec.ts
  • projects/dashboards-demo/src/environments/environment.ts
  • playwright.config.ts
  • projects/dashboards-demo/mfe/src/main.ts
  • projects/dashboards-demo/src/main.ts
  • projects/dashboards-ng/native-federation/mf-bridge/index.ts
📚 Learning: 2025-12-12T11:44:21.060Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1188
File: projects/maps-ng/tsconfig.lib.json:16-18
Timestamp: 2025-12-12T11:44:21.060Z
Learning: Maintain broad include patterns in tsconfig.lib.json files. Do not narrow include from "./**/*.ts" to "./src/**/*.ts" unless there is a strong, project-wide reason. This ensures library code outside src (e.g., folders like translate/) remains part of the compilation in solution-style TypeScript configurations. When reviewing, verify that each tsconfig.lib.json retains a broad include pattern that covers all TypeScript sources intended for the library, not just those under src.

Applied to files:

  • projects/dashboards-ng/tsconfig.lib.json
📚 Learning: 2025-12-17T06:59:51.485Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1036
File: projects/dashboards-ng/src/widget-loader.ts:176-182
Timestamp: 2025-12-17T06:59:51.485Z
Learning: In projects/dashboards-ng/src/widget-loader.ts, when checking `factory.moduleName`, there's no need to also check for `factory.moduleLoader` because the TypeScript type system (ModuleOptions type) enforces that `moduleLoader` must be present whenever `moduleName` is provided.

Applied to files:

  • projects/dashboards-ng/tsconfig.lib.json
  • projects/dashboards-ng/native-federation/index.ts
  • projects/dashboards-ng/src/model/widgets.model.ts
  • projects/dashboards-demo/src/app/widgets/module-federation-widgets.ts
  • projects/dashboards-demo/mfe/src/main.ts
  • projects/dashboards-ng/native-federation/mf-bridge/index.ts
📚 Learning: 2025-12-12T11:44:30.712Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1188
File: projects/maps-ng/tsconfig.lib.json:16-18
Timestamp: 2025-12-12T11:44:30.712Z
Learning: In projects/maps-ng/tsconfig.lib.json, the include pattern "./**/*.ts" should remain broad and not be restricted to "./src/**/*.ts", as files outside src/ (like those in translate/) are intentionally part of the library compilation in the solution-style TypeScript configuration.

Applied to files:

  • projects/dashboards-ng/native-federation/mf-bridge/ng-package.json
  • projects/dashboards-ng/native-federation/ng-package.json
  • projects/dashboards-demo/tsconfig.app.json
  • .gitignore
  • projects/dashboards-demo/eslint.config.js
  • projects/dashboards-demo/tsconfig.app.prod.json
  • projects/dashboards-demo/mfe/tsconfig.app.json
  • projects/dashboards-demo/webcomponents/eslint.config.js
📚 Learning: 2025-12-22T13:26:40.908Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1237
File: tools/api-goldens/test_api_report.ts:19-23
Timestamp: 2025-12-22T13:26:40.908Z
Learning: In the siemens/element repository, the team intentionally uses internal APIs from `microsoft/api-extractor` (such as `AstDeclaration`, `AstModule`, `ExportAnalyzer`, `ApiItemMetadata`, and `Collector` from `/lib/analyzer` and `/lib/collector` paths) in `tools/api-goldens/test_api_report.ts` to customize API extraction behavior (e.g., marking protected members as internal). This is an accepted practice because the required functionality is not available through the public API, and the version is pinned to mitigate risks.

Applied to files:

  • api-goldens/dashboards-ng/native-federation/index.api.md
  • api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md
📚 Learning: 2025-12-23T09:24:35.163Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/translate/index.api.md:12-84
Timestamp: 2025-12-23T09:24:35.163Z
Learning: In the siemens/element repository, do not review files under the api-goldens/ directory (e.g., api-goldens/**/index.api.md) since they are auto-generated by API Extractor. Exclude these from review checks and focus on source files that are not auto-generated.

Applied to files:

  • api-goldens/dashboards-ng/native-federation/index.api.md
  • api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md
  • api-goldens/dashboards-ng/index.api.md
📚 Learning: 2025-12-23T09:24:57.843Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/index.api.md:324-325
Timestamp: 2025-12-23T09:24:57.843Z
Learning: Do not review files in the api-goldens directory, as they are auto-generated API reports produced by API Extractor.

Applied to files:

  • api-goldens/dashboards-ng/native-federation/index.api.md
  • api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md
  • api-goldens/dashboards-ng/index.api.md
📚 Learning: 2025-12-23T09:24:40.395Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1235
File: api-goldens/dashboards-ng/module-federation/index.api.md:7-11
Timestamp: 2025-12-23T09:24:40.395Z
Learning: In the siemens/element repository, do not review any files under the api-goldens directory, as they are auto-generated API reports produced by API Extractor. These MD files should be excluded from review unless explicitly overridden.

Applied to files:

  • api-goldens/dashboards-ng/native-federation/index.api.md
  • api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md
  • api-goldens/dashboards-ng/index.api.md
📚 Learning: 2025-12-16T16:19:17.950Z
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:17.950Z
Learning: Do not review files in the playwright/snapshots directory, as they contain auto-generated test artifacts. Exclude any YAML snapshot files under playwright/snapshots from code reviews in the siemens/element repository. If a YAML file is not an auto-generated snapshot, verify its origin before skipping.

Applied to files:

  • playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--esm-edit.yaml
📚 Learning: 2025-12-15T07:17:06.981Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts:37-49
Timestamp: 2025-12-15T07:17:06.981Z
Learning: In widget-instance-editor-dialog component tests (projects/dashboards-ng/src/components/widget-instance-editor-dialog/si-widget-instance-editor-dialog.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing component initialization. This is likely due to the component's lifecycle behavior or modal initialization timing that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • playwright/e2e/dashboards-demo/dashboard.spec.ts
📚 Learning: 2025-12-15T07:16:53.762Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:92-105
Timestamp: 2025-12-15T07:16:53.762Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits must be used instead of fixture.whenStable() to avoid injector destroyed errors during mount/unmount operations in zoneless mode. The GridStack timing-dependent operations require actual async delays.

Applied to files:

  • playwright/e2e/dashboards-demo/dashboard.spec.ts
📚 Learning: 2025-12-15T07:16:32.082Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1191
File: projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts:69-80
Timestamp: 2025-12-15T07:16:32.082Z
Learning: In gridstack-wrapper component tests (projects/dashboards-ng/src/components/gridstack-wrapper/si-gridstack-wrapper.component.spec.ts), real setTimeout waits (e.g., `await new Promise(resolve => setTimeout(resolve, 0))`) must be used instead of `fixture.whenStable()` when testing grid item rendering and initialization. This is likely due to gridstack library's initialization timing or lifecycle behavior that fixture.whenStable() cannot properly wait for in zoneless mode.

Applied to files:

  • playwright/e2e/dashboards-demo/dashboard.spec.ts
📚 Learning: 2025-12-15T10:05:59.100Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1193
File: projects/element-ng/search-bar/si-search-bar.component.spec.ts:21-28
Timestamp: 2025-12-15T10:05:59.100Z
Learning: In tests that rely on Jasmine's fake clock to control time-based RxJS operators (e.g., debounceTime), use jasmine.clock().install() together with jasmine.clock().mockDate() to enable precise timing control. Without mockDate, scheduler-based operators may not respond to the fake clock. Apply this guidance to spec files (e.g., any file named *.spec.ts or *.spec.js) that test time-sensitive behavior, ensuring you install and mockDate before advancing time in tests.

Applied to files:

  • playwright/e2e/dashboards-demo/dashboard.spec.ts
📚 Learning: 2026-01-07T12:19:38.754Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1240
File: projects/dashboards-ng/package.json:21-22
Timestamp: 2026-01-07T12:19:38.754Z
Learning: In the siemens/element repository, Angular peer dependencies are intentionally pinned to exact major versions (e.g., "angular/core": "21") rather than ranges in package.json files for published packages like siemens/dashboards-ng, siemens/element-ng, and siemens/element-translate-ng. This is a deliberate strategy to ensure strict version alignment.

Applied to files:

  • package.json
📚 Learning: 2025-12-09T14:19:26.605Z
Learnt from: Killusions
Repo: siemens/element PR: 967
File: package.json:153-153
Timestamp: 2025-12-09T14:19:26.605Z
Learning: In library projects (e.g., element-ng), do not list implementation dependencies for optional features in the main dependencies. Move those into devDependencies (used for demos/examples) and have consuming apps install them separately if they enable the feature. This avoids bloating library consumers with unnecessary packages and clarifies that optional features are not guaranteed to work without extra installs. If a feature is truly optional, consider documenting it and, if appropriate, using optionalDependencies to reflect optional runtime usage.

Applied to files:

  • package.json
📚 Learning: 2026-01-07T19:44:24.336Z
Learnt from: spliffone
Repo: siemens/element PR: 453
File: projects/element-translate-ng/package.json:26-26
Timestamp: 2026-01-07T19:44:24.336Z
Learning: In this repository, peerDependencies in package.json should use hyphen-major-version ranges (e.g., '16 - 17', '22 - 25') instead of standard semver ranges like '>=16.0.0 <18.0.0' or '^16.0.0 || ^17.0.0'. This convention is applied across all packages for consistency. During reviews, verify that each package.json lists peerDependencies using a hyphen-range format, and update any that use conventional semver expressions. If needed, adjust to the correct major-version bounds (e.g., '16 - 17' for 16.x/17.x).

Applied to files:

  • package.json
📚 Learning: 2025-12-01T04:01:27.365Z
Learnt from: chintankavathia
Repo: siemens/element PR: 1099
File: projects/element-ng/accordion/si-accordion.component.spec.ts:39-43
Timestamp: 2025-12-01T04:01:27.365Z
Learning: With Angular 20 and esbuild, synchronous `TestBed.configureTestingModule(...).compileComponents()` calls work correctly even when components use external templates (templateUrl), because esbuild pre-compiles templates at build time. The async/await pattern is not required in this scenario.

Applied to files:

  • projects/dashboards-demo/webcomponents/concat.cjs
  • angular.json
🧬 Code graph analysis (9)
projects/dashboards-demo/mfe/src/environments/environment.ts (5)
projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.esm.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.prod.ts (1)
  • environment (6-10)
projects/dashboards-demo/src/environments/environment.esm.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.ts (1)
  • environment (10-15)
projects/dashboards-demo/mfe/src/environments/environment.esm.ts (6)
projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.prod.ts (1)
  • environment (6-10)
projects/dashboards-demo/mfe/src/environments/environment.ts (1)
  • environment (10-14)
projects/dashboards-demo/src/environments/environment.esm.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.prod.ts (1)
  • environment (6-11)
projects/dashboards-demo/src/environments/environment.ts (1)
  • environment (10-15)
projects/dashboards-demo/mfe/src/environments/environment.prod.ts (3)
projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts (1)
  • environment (9-13)
projects/dashboards-demo/src/environments/environment.esm.prod.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.prod.ts (1)
  • environment (6-11)
projects/dashboards-demo/federation.config.js (2)
projects/dashboards-demo/mfe/federation.config.js (1)
  • require (1-1)
projects/dashboards-demo/webpack.config.cjs (1)
  • require (1-4)
projects/dashboards-ng/native-federation/index.ts (2)
projects/dashboards-ng/src/model/widgets.model.ts (1)
  • FederatedModule (84-88)
projects/dashboards-ng/src/widget-loader.ts (2)
  • widgetFactoryRegistry (32-46)
  • SetupComponentFn (24-30)
projects/dashboards-demo/src/app/widgets/module-federation-widgets.ts (9)
projects/dashboards-ng/src/model/widgets.model.ts (1)
  • Widget (16-44)
projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.esm.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.prod.ts (1)
  • environment (6-10)
projects/dashboards-demo/mfe/src/environments/environment.ts (1)
  • environment (10-14)
projects/dashboards-demo/src/environments/environment.esm.prod.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.esm.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.prod.ts (1)
  • environment (6-11)
projects/dashboards-demo/src/environments/environment.ts (1)
  • environment (10-15)
playwright/e2e/dashboards-demo/dashboard.spec.ts (1)
playwright/support/test-helpers.ts (1)
  • test (286-296)
projects/dashboards-demo/src/main.ts (8)
projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.esm.ts (1)
  • environment (9-13)
projects/dashboards-demo/mfe/src/environments/environment.prod.ts (1)
  • environment (6-10)
projects/dashboards-demo/mfe/src/environments/environment.ts (1)
  • environment (10-14)
projects/dashboards-demo/src/environments/environment.esm.prod.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.esm.ts (1)
  • environment (9-14)
projects/dashboards-demo/src/environments/environment.prod.ts (1)
  • environment (6-11)
projects/dashboards-demo/src/environments/environment.ts (1)
  • environment (10-15)
projects/dashboards-ng/native-federation/mf-bridge/index.ts (2)
projects/dashboards-ng/src/model/widgets.model.ts (1)
  • FederatedBridgeModule (90-94)
projects/dashboards-ng/src/widget-loader.ts (2)
  • widgetFactoryRegistry (32-46)
  • SetupComponentFn (24-30)
🪛 markdownlint-cli2 (0.18.1)
api-goldens/dashboards-ng/native-federation/index.api.md

1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md

1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (42)
projects/dashboards-demo/eslint.config.js (1)

8-12: ✅ ESLint ignores correctly updated for ESM environment files.

The expansion of the ignores array to include the new ESM environment variants (environment.esm.ts and environment.esm.prod.ts) aligns with the native federation setup introduced in this PR. The glob patterns are correct and consistent with the existing approach of excluding generated/build-time environment configurations.

.gitignore (1)

71-74: The gitignore entries for Native Federation tsconfig files are correct and complete.

The added entries properly ignore the generated federation tsconfig files. Verification confirms that:

  1. /projects/dashboards-demo/mfe/ correctly references a subdirectory (not a separate project)
  2. Both federation build targets (main app and mfe) are covered
  3. The webcomponents directory does not use Native Federation and requires no additional ignore entries

No changes needed.

projects/dashboards-demo/tsconfig.app.json (1)

9-16: The configuration is correct and no changes are needed. The base environment.ts is properly included for compilation, and Angular's fileReplacements in angular.json correctly handle swapping environment variants during the build process (e.g., environment.prod.ts for production, environment.esm.ts for ESM builds). Excluding the variant files is a standard Angular pattern—these files are applied at build time via fileReplacements, not through TypeScript's module resolution.

Likely an incorrect or invalid review comment.

projects/dashboards-demo/mfe/tsconfig.app.json (1)

7-8: Remove the explicit environment files inclusion from the include array.

The addition of "src/main.esm.ts" to the files array is correct for native federation support.

However, the explicit "src/environments/*.ts" inclusion in the include array is unnecessary. These environment files are not imported anywhere in the mfe codebase (main.ts, main.esm.ts, bootstrap.ts, or any other component files). Since TypeScript automatically includes imported files through dependency resolution, explicitly listing unused files adds unnecessary configuration. Remove "src/environments/*.ts" from the include array on line 8.

⛔ Skipped due to learnings
Learnt from: spike-rabbit
Repo: siemens/element PR: 1188
File: projects/maps-ng/tsconfig.lib.json:16-18
Timestamp: 2025-12-12T11:44:30.712Z
Learning: In projects/maps-ng/tsconfig.lib.json, the include pattern "./**/*.ts" should remain broad and not be restricted to "./src/**/*.ts", as files outside src/ (like those in translate/) are intentionally part of the library compilation in the solution-style TypeScript configuration.
projects/dashboards-ng/native-federation/ng-package.json (1)

1-6: index.ts exists and correctly exports the native federation widget loader.

The file projects/dashboards-ng/native-federation/index.ts is present and exports registerNativeFederatedWidgetLoader, the intended public API for this secondary entrypoint. The ng-package.json configuration is valid.

projects/dashboards-demo/webcomponents/eslint.config.js (1)

4-13: The ESLint configuration change is safe. No *.spec.ts or *.test.ts files exist in this directory, and tsconfig.spec.json does not exist. The narrowed parserOptions.project pointing only to tsconfig.app.json is appropriate and does not require the proposed spec override block.

.github/workflows/build-and-test.yaml (1)

267-270: No action needed — dist/dashboards-demo-esm/ is a stable, consistently-named output directory.

The output path is explicitly configured in angular.json with a fixed value ("base": "dist/dashboards-demo-esm"), not a variable or configuration-dependent setting. The npm run dashboards-demo:build:esm build step executes unconditionally in the workflow and always produces this directory. The path is also consistently referenced throughout the codebase (federation config, npm scripts, and Playwright tests), confirming its stability.

projects/dashboards-demo/mfe/src/environments/environment.esm.prod.ts (1)

5-13: The mfeBaseUrl value is correct for the deployed folder structure. The relative path ./mfe-esm properly resolves to the MFE's output directory during native federation setup. No changes needed.

Regarding the empty /** */ comment: this is a codebase-wide convention (found in 40+ files) that precedes exported entities after SPDX headers. Removing it from this file alone would be inconsistent; any cleanup should be addressed as a bulk refactoring across the codebase if desired.

projects/dashboards-demo/src/styles-esm.scss (1)

1-20: Remove direct /src/ imports from @siemens/element-theme—package lacks proper export configuration.

The file is correctly wired into the ESM build (angular.json:510), but the imports from @siemens/element-theme/src/theme and @siemens/element-theme/src/styles/themes will likely fail to resolve. The local @siemens/element-theme workspace package has no "main", "exports", or "sass" field defined in its package.json, and it's not mapped in tsconfig.json. Either add a tsconfig path mapping for @siemens/element-theme, configure proper exports in the package.json, or use the built output path if available.

⛔ Skipped due to learnings
Learnt from: spike-rabbit
Repo: siemens/element PR: 1188
File: projects/maps-ng/tsconfig.lib.json:16-18
Timestamp: 2025-12-12T11:44:30.712Z
Learning: In projects/maps-ng/tsconfig.lib.json, the include pattern "./**/*.ts" should remain broad and not be restricted to "./src/**/*.ts", as files outside src/ (like those in translate/) are intentionally part of the library compilation in the solution-style TypeScript configuration.
Learnt from: mistrykaran91
Repo: siemens/element PR: 1234
File: projects/element-ng/ag-grid/parts/radio-style.part.ts:15-61
Timestamp: 2025-12-31T07:16:13.451Z
Learning: In the AG Grid theme package (projects/element-ng/ag-grid), styling should maintain consistency with the base Element design system components rather than adding enhancements or extra CSS. If accessibility improvements like focus-visible indicators are needed, they should be implemented at the Element design system level first.
Learnt from: spike-rabbit
Repo: siemens/element PR: 1207
File: playwright/snapshots/si-filtered-search.spec.ts-snapshots/si-filtered-search--si-filtered-search-playground--data-entered.yaml:38-38
Timestamp: 2025-12-16T16:19:24.628Z
Learning: Do not review files in the `playwright/snapshots/` directory in the siemens/element repository as they are auto-generated test artifacts.
projects/dashboards-demo/webcomponents/concat.cjs (1)

18-33: LGTM!

The IIFE wrapping pattern effectively isolates scope and prevents variable conflicts across concatenated files. The multi-target output strategy (module federation, native federation ESM, and webcomponents) aligns well with the PR's federation approach.

projects/dashboards-demo/mfe/src/environments/environment.ts (1)

10-14: LGTM!

The environment configuration is well-structured and consistent with the pattern used across other environment files. The useModuleFederation flag enables clean runtime switching between Module Federation and Native Federation modes.

projects/dashboards-ng/native-federation/index.ts (2)

44-46: LGTM!

The registration function correctly wires the native federation loader into the widget factory registry, enabling runtime widget loading for native federation scenarios.


22-22: No change needed. The double property access pattern module[factory[componentName]] is intentional and type-safe. The FederatedModule type explicitly allows arbitrary string keys via [index: string]: any, enabling a standard dictionary-to-array lookup pattern where factory[componentName] retrieves a mapped value that indexes into the component array. This pattern is consistently implemented across all federation loaders (native-federation, module-federation, and mf-bridge) and is part of the deliberate module federation design.

projects/dashboards-demo/webpack.config.cjs (1)

6-20: LGTM!

The webpack configuration correctly excludes ESM-only native federation packages from webpack processing. The use of commonjs externals prevents build errors while maintaining compatibility with the module federation setup. The comment clearly documents the rationale.

projects/dashboards-ng/src/model/widgets.model.ts (3)

47-51: LGTM: Union type expansion is correct.

The addition of FederatedBridgeModule to the WidgetComponentFactory union properly supports the new native-federation bridge scenario described in the PR objectives.


84-88: Verify the addition of the index signature to FederatedModule.

The factoryType expansion to include 'native-federation' aligns with the PR's native federation support. However, the addition of [index: string]: any allows arbitrary properties on FederatedModule, which could weaken type safety.

Could you clarify whether the index signature is intentional and necessary? If it's meant to accommodate federation-specific configuration properties, consider documenting this or using a more constrained type like [key: string]: unknown to maintain better type discipline.


90-94: LGTM: FederatedBridgeModule type definition is well-structured.

The new type correctly combines CommonFactoryFields, LoadRemoteBridgeOptions, and a specific factoryType discriminator for the module-federation bridge scenario.

api-goldens/dashboards-ng/index.api.md (1)

1-430: Skipping review: Auto-generated API report.

This file is auto-generated by API Extractor and should not be manually reviewed. Based on learnings, API golden files are excluded from review as they reflect the public API surface extracted from source files.

projects/dashboards-ng/native-federation/mf-bridge/ng-package.json (1)

1-6: LGTM: Standard ng-packagr configuration.

The configuration correctly sets up the native-federation mf-bridge subpackage with a standard entry file reference. This aligns with Angular library packaging conventions.

projects/dashboards-demo/mfe/src/main.ts (1)

6-7: LGTM: Clear documentation of entry point purpose.

The comments effectively clarify the distinction between webpack-based Module Federation (this file) and Native Federation ESM builds (main.esm.ts), helping developers choose the correct entry point for their build configuration.

projects/dashboards-demo/src/environments/environment.esm.prod.ts (1)

9-14: LGTM!

The environment configuration is complete and correct for ESM production builds. All required properties are present (mfeBaseUrl, mfeEsmBaseUrl, webComponentsBaseUrl, useModuleFederation), and the values are appropriate for a production deployment using native federation.

projects/dashboards-demo/mfe/src/environments/environment.prod.ts (1)

6-10: LGTM!

The environment configuration is correct for the MFE (remote) production build using module federation. The properties are appropriate, and the useModuleFederation: true flag correctly indicates this is a module federation configuration.

package.json (2)

67-81: LGTM!

The new npm scripts are well-organized and provide comprehensive support for ESM/native federation workflows, including separate commands for development (start:esm, start:mfe:esm) and production builds (build:esm, build:esm:mfe, build:bridge:mfe).


108-109: Update @angular-architects/native-federation to 21.0.3 and review @module-federation/enhanced version compatibility.

@angular-architects/native-federation 21.0.0 is outdated; version 21.0.3 is the latest stable release for Angular 21.x and should be used instead.

@module-federation/enhanced 0.22.0 exceeds the typical 0.15–0.21 version range used in Angular 21.x/22.x workflows; verify this version is intentional and compatible with your webpack and @Angular-devkit setup.

@softarc/native-federation-node ^3.3.4 is acceptable (3.3.5 is available but patch-level).

es-module-shims ^1.5.12 is significantly outdated (v2.6.2+ is current), but Angular 21's ESM-first architecture typically does not require this polyfill unless supporting older browsers or unbundled ESM with import maps.

⛔ Skipped due to learnings
Learnt from: chintankavathia
Repo: siemens/element PR: 1240
File: projects/dashboards-ng/package.json:21-22
Timestamp: 2026-01-07T12:19:38.754Z
Learning: In the siemens/element repository, Angular peer dependencies are intentionally pinned to exact major versions (e.g., "angular/core": "21") rather than ranges in package.json files for published packages like siemens/dashboards-ng, siemens/element-ng, and siemens/element-translate-ng. This is a deliberate strategy to ensure strict version alignment.
Learnt from: spliffone
Repo: siemens/element PR: 453
File: projects/element-translate-ng/ngx-translate/si-translate-ngxt.service.ts:42-44
Timestamp: 2026-01-05T16:46:16.913Z
Learning: In projects/element-translate-ng, the peer dependency range for ngx-translate/core includes both v16 and v17, requiring use of APIs compatible with both versions. The deprecated properties `currentLang`, `getDefaultLang()`, and `setDefaultLang()` must be used instead of their v17 replacements (`getCurrentLang()`, `getFallbackLang()`, `setFallbackLang()`) until v16 support is dropped in v49.
Learnt from: spliffone
Repo: siemens/element PR: 453
File: projects/element-translate-ng/package.json:26-26
Timestamp: 2026-01-07T19:44:24.336Z
Learning: In the siemens/element repository, peer dependencies in package.json files use hyphen range syntax (e.g., "16 - 17", "22 - 25") to specify support for multiple major versions, rather than standard semver range syntax like ">=16.0.0 <18.0.0" or "^16.0.0 || ^17.0.0". This is an intentional project convention for consistency across all packages.
projects/dashboards-demo/src/environments/environment.ts (1)

10-15: LGTM!

The new mfeEsmBaseUrl and useModuleFederation properties are correctly added and align with the other environment configurations in the PR. The useModuleFederation: true setting correctly indicates this is the default module federation environment.

api-goldens/dashboards-ng/native-federation/mf-bridge/index.api.md (1)

1-14: Skipping review of auto-generated API golden file.

Based on learnings, files under api-goldens/ are auto-generated by API Extractor and should not be reviewed.

playwright.config.ts (3)

10-17: LGTM!

The ESM port configuration and server command are correctly set up, with port 4204 for the ESM host app and the server command pointing to dist/dashboards-demo-esm.


169-184: LGTM!

The new ESM project definitions correctly mirror the existing dashboards-demo projects, using the ESM port and sharing the same test directory. This enables running the same E2E tests against both module federation and native federation builds.


206-214: LGTM!

The conditional web server startup for ESM projects follows the same pattern as the existing dashboards-demo server configuration.

projects/dashboards-demo/src/environments/environment.esm.ts (1)

1-14: LGTM!

The ESM environment configuration correctly sets useModuleFederation: false to trigger the native federation initialization path and includes both federation URLs to support the mf-bridge hybrid scenario.

projects/dashboards-demo/src/environments/environment.prod.ts (1)

6-11: LGTM!

The production environment correctly adds mfeEsmBaseUrl with a relative path and sets useModuleFederation: true for the standard production build using module federation.

projects/dashboards-demo/federation.config.js (1)

1-39: LGTM overall!

The native federation configuration is well-structured with appropriate shared settings, skip patterns for problematic packages, and clear comments explaining the configuration choices.

projects/dashboards-demo/mfe/federation.config.js (1)

1-24: LGTM! Standard native federation configuration.

The configuration correctly:

  • Exposes the Download and Upload components for remote consumption
  • Skips browser-incompatible packages (rxjs submodules, flag-icons)
  • Uses shareAll with appropriate settings for singleton shared dependencies
projects/dashboards-ng/native-federation/mf-bridge/index.ts (1)

48-56: LGTM! Clean registration pattern.

The function properly binds the ModuleFederation instance and registers under the correct factory type key (nf-module-federation) matching the FederatedBridgeModule type definition.

playwright/snapshots/dashboard.spec.ts-snapshots/dashboard--esm-edit.yaml (1)

1-44: Skipping review of auto-generated Playwright snapshot.

Based on learnings, files in playwright/snapshots are auto-generated test artifacts and should not be reviewed.

projects/dashboards-demo/src/app/widgets/module-federation-widgets.ts (2)

9-31: LGTM! Clean environment-based widget configuration.

The DOWNLOAD_WIDGET correctly branches between module-federation (.js remote entry) and native-federation (.json remote entry) configurations based on the environment flag.


45-53: No action required. The nf-module-federation configuration is correct and has all required fields as defined by the FederatedBridgeModule type: factoryType, id, and componentName. The fields present in the module-federation variant (type, remoteEntry, exposedModule) are not part of the nf-module-federation contract—they belong to different module federation approaches. The bridge module uses the id field to identify the remote, while classic module federation uses remoteEntry and exposedModule paths. The TypeScript type system ensures type safety for required fields.

Likely an incorrect or invalid review comment.

angular.json (5)

479-556: LGTM! Well-structured esbuild configuration for native federation.

The esbuild target correctly configures:

  • ESM-specific environment file replacements
  • es-module-shims polyfill for import map support
  • Separate styles file (styles-esm.scss)
  • Appropriate CommonJS dependency allowlist including @module-federation/runtime

Production configuration has proper optimization, hashing, and budget settings.


558-597: LGTM! Native federation serve chain properly configured.

The three-target chain (serve-esmserve-esm-originalbuild-esmesbuild) follows the recommended pattern from @angular-architects/native-federation. The rebuildDelay: 500 and cacheExternalArtifacts: false are appropriate for development.


611-665: LGTM! Clean migration to @angular/build:application builder.

The webcomponents project correctly migrates to the new Angular application builder with:

  • Object-based outputPath configuration
  • browser entry point (renamed from main)
  • Matching @angular/build:dev-server for serve

726-728: Confirm bridge configuration intent.

The bridge configuration only overrides outputPath to dist/dashboards-demo-esm/mfe. This places the module-federation build output alongside the native-federation shell, which aligns with the mf-bridge use case (NF shell loading MF remotes).


759-852: LGTM! MFE esbuild and native federation targets properly configured.

The configuration correctly:

  • Uses main.esm.ts as browser entry point for ESM builds
  • Outputs to dist/dashboards-demo-esm/mfe-esm
  • Includes es-module-shims polyfill
  • Serves on port 4205 (matching environment.mfeEsmBaseUrl)

@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 3 times, most recently from 4ee9421 to ecf9557 Compare January 12, 2026 09:13
@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch from ecf9557 to 7c57c45 Compare January 19, 2026 09:26
@chintankavathia chintankavathia requested a review from a team as a code owner January 19, 2026 09:26
@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 7 times, most recently from 473580f to 6dd85b0 Compare January 19, 2026 12:30
@timowolf
Copy link
Member

Adding Upload (module-federation on native-federation shell) to the ESM version on the online demo at https://d33c9dcnqinn2a.cloudfront.net/pr-1265/pages/dashboards-demo-esm/#/dashboard does not work. Is an empty widget

Copy link
Member

@timowolf timowolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic work. Just a bit of documentation. You started in the PR already. I think this should go into a README. The upload widget does not work online in the PR demo for esm.

@timowolf timowolf added this to the 49.0.0 milestone Jan 26, 2026
@timowolf timowolf added the feature Marks feature requests and feature implementations label Jan 26, 2026
@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 3 times, most recently from 082fee1 to d29617c Compare January 27, 2026 06:23
@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch from fff4b85 to 71108b4 Compare January 27, 2026 06:56
@chintankavathia
Copy link
Member Author

Adding Upload (module-federation on native-federation shell) to the ESM version on the online demo at https://d33c9dcnqinn2a.cloudfront.net/pr-1265/pages/dashboards-demo-esm/#/dashboard does not work. Is an empty widget

This is fixed.

@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 13 times, most recently from f06761c to ec07310 Compare January 29, 2026 04:21
@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 2 times, most recently from 46b29bd to 863435b Compare January 29, 2026 06:02
Copy link
Member

@timowolf timowolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@timowolf timowolf force-pushed the feat/dashboards/native-federation branch from 863435b to 5847f2f Compare January 30, 2026 12:40
@timowolf timowolf enabled auto-merge (rebase) January 30, 2026 12:40
@chintankavathia chintankavathia force-pushed the feat/dashboards/native-federation branch 3 times, most recently from 43222ce to ec0d42a Compare January 30, 2026 13:56
added `registerNativeFederatedWidgetLoader` for pure native federation setup and `registerModuleFederatedWidgetLoader` for remote using module federation and shell on native federation.
@timowolf timowolf force-pushed the feat/dashboards/native-federation branch from ec0d42a to 399356c Compare January 30, 2026 14:41
@github-actions
Copy link

Code Coverage

Copy link
Member

@spike-rabbit spike-rabbit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@timowolf timowolf merged commit f81c5a4 into main Jan 30, 2026
11 checks passed
@timowolf timowolf deleted the feat/dashboards/native-federation branch January 30, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Marks feature requests and feature implementations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants