nx: Error: "inject() must be called from an injection context such as a constructor" when loading remote Angular application from host app

Current Behavior

After migrating NX from 16.2.2 -> 16.8.1 our remote (using module federation) applications failes with this error:

NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`

They work as standalone applications but not remotes. I.e when I go to http://locahost:4201 it loads the dashboard, but not when trying to load it as a route in our host-app.

It might be related to this issue: https://github.com/nrwl/nx/issues/17696 And/or maybe this issue: https://github.com/angular/angular/issues/51532

The module federation is setup according to the guide.

Expected Behavior

It should not fail to run the application as a remote application using module federation.

GitHub Repo

https://github.com/JonWallsten/nx-repro

Steps to Reproduce

  1. clone repo
  2. npm i
  3. npx nx serve host

Or from scratch:

  1. npx create-nx-workspace debug
  2. npx nx migrate latest
  3. npx nx g @nx/angular:host host
  4. npx nx g @nx/angular:remote remote --host=host
  5. npx nx serve host

Nx Report

>  NX   Report complete - copy this into the issue template

   Node   : 18.14.1
   OS     : win32-x64
   npm    : 9.3.1

   nx                 : 16.8.1
   @nx/js             : 16.8.1
   @nx/jest           : 16.8.1
   @nx/linter         : 16.8.1
   @nx/workspace      : 16.8.1
   @nx/angular        : 16.8.1
   @nx/cypress        : 16.8.1
   @nx/devkit         : 16.8.1
   @nx/eslint-plugin  : 16.8.1
   @nrwl/tao          : 16.8.1
   @nx/web            : 16.8.1
   @nx/webpack        : 16.8.1
   typescript         : 5.1.6

Failure Logs

Error: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.io/errors/NG0203
    at injectInjectorOnly (core.mjs:731:15)
    at Module.ɵɵinject (core.mjs:744:60)
    at Object._class6_Factory [as factory] (common.mjs:67:84)
    at core.mjs:9412:43
    at runInInjectorProfilerContext (core.mjs:694:9)
    at R3Injector.hydrate (core.mjs:9411:17)
    at R3Injector.get (core.mjs:9281:33)
    at injectInjectorOnly (core.mjs:738:40)
    at ɵɵinject (core.mjs:744:60)
    at inject (core.mjs:828:12)

Package Manager Version

9.3.1

Operating System

  • Windows

Additional Information

About this issue

  • Original URL
  • State: open
  • Created 10 months ago
  • Reactions: 7
  • Comments: 19 (1 by maintainers)

Most upvoted comments

After adding @angular/core and @angular/router manually here before building the remote: https://github.com/nrwl/nx/blob/dde91067f0ddd7bd7199f3727fc19dd4ca1f7c07/packages/angular/src/utils/mf/utils.ts#L109-L118

The application works fine again. So that begs the question: Why is @angular/core and @angular/router missing as dependencies for the remote? image

Edit: I get it now. No dependecies at all is found. Common/Animations are from some kind of constant called DEFAULT_ANGULAR_PACKAGES_TO_SHARE

MfConfig {
  name: 'remote',
  exposes: { './Module': 'apps/remote/src/app/remote-entry/entry.module.ts' }
}
projectGraph {
  nodes: {
    remote: { name: 'remote', type: 'app', data: [Object] },
    host: { name: 'host', type: 'app', data: [Object] }
  },
  externalNodes: {},
  dependencies: { remote: [], host: [] },
  version: '6.0'
}
mfConfig.name remote
Dependencies { workspaceLibraries: [], npmPackages: [] }
workspaceLibraries []
npmPackages []
sharedLibraries {
  getAliases: [Function: getAliases],
  getLibraries: [Function: getLibraries],
  getReplacementPlugin: [Function: getReplacementPlugin]
}
DEFAULT_ANGULAR_PACKAGES_TO_SHARE [ '@angular/animations', '@angular/common' ]
dependencies.npmPackages []
npmPackages {
  '@angular/animations': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/animations/browser': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common/testing': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common/upgrade': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' }
}
sharedDependencies apps/remote {}
sharedDependencies {
  '@angular/animations': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/animations/browser': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common/testing': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' },
  '@angular/common/upgrade': { singleton: true, strictVersion: true, requiredVersion: '16.2.4' }
}

Same output from 16.2.2:

MfConfig {
  name: 'remote',
  exposes: { './Module': 'apps/remote/src/app/remote-entry/entry.module.ts' }
}
projectGraph {
  version: '5.1',
  nodes: {
    remote: { name: 'remote', type: 'app', data: [Object] },
    host: { name: 'host', type: 'app', data: [Object] }
  },
  externalNodes: {
    'npm:@angular/animations': { type: 'npm', name: 'npm:@angular/animations', data: [Object] },
    'npm:@angular/common': { type: 'npm', name: 'npm:@angular/common', data: [Object] },
    'npm:@angular/compiler': { type: 'npm', name: 'npm:@angular/compiler', data: [Object] },
    'npm:@angular/core': { type: 'npm', name: 'npm:@angular/core', data: [Object] },
    'npm:@angular/forms': { type: 'npm', name: 'npm:@angular/forms', data: [Object] },
    'npm:@angular/platform-browser': {
      type: 'npm',
      name: 'npm:@angular/platform-browser',
      data: [Object]
    },
    'npm:@angular/platform-browser-dynamic': {
      type: 'npm',
      name: 'npm:@angular/platform-browser-dynamic',
      data: [Object]
    },
    'npm:@angular/router': { type: 'npm', name: 'npm:@angular/router', data: [Object] },
    'npm:@nx/angular': { type: 'npm', name: 'npm:@nx/angular', data: [Object] },
    'npm:rxjs': { type: 'npm', name: 'npm:rxjs', data: [Object] },
    'npm:tslib': { type: 'npm', name: 'npm:tslib', data: [Object] },
    'npm:zone.js': { type: 'npm', name: 'npm:zone.js', data: [Object] },
    'npm:@angular-devkit/build-angular': {
      type: 'npm',
      name: 'npm:@angular-devkit/build-angular',
      data: [Object]
    },
    'npm:@angular-devkit/core': { type: 'npm', name: 'npm:@angular-devkit/core', data: [Object] },
    'npm:@angular-devkit/schematics': {
      type: 'npm',
      name: 'npm:@angular-devkit/schematics',
      data: [Object]
    },
    'npm:@angular-eslint/eslint-plugin': {
      type: 'npm',
      name: 'npm:@angular-eslint/eslint-plugin',
      data: [Object]
    },
    'npm:@angular-eslint/eslint-plugin-template': {
      type: 'npm',
      name: 'npm:@angular-eslint/eslint-plugin-template',
      data: [Object]
    },
    'npm:@angular-eslint/template-parser': {
      type: 'npm',
      name: 'npm:@angular-eslint/template-parser',
      data: [Object]
    },
    'npm:@angular/cli': { type: 'npm', name: 'npm:@angular/cli', data: [Object] },
    'npm:@angular/compiler-cli': { type: 'npm', name: 'npm:@angular/compiler-cli', data: [Object] },
    'npm:@angular/language-service': {
      type: 'npm',
      name: 'npm:@angular/language-service',
      data: [Object]
    },
    'npm:@nx/cypress': { type: 'npm', name: 'npm:@nx/cypress', data: [Object] },
    'npm:@nx/eslint-plugin': { type: 'npm', name: 'npm:@nx/eslint-plugin', data: [Object] },
    'npm:@nx/jest': { type: 'npm', name: 'npm:@nx/jest', data: [Object] },
    'npm:@nx/js': { type: 'npm', name: 'npm:@nx/js', data: [Object] },
    'npm:@nx/linter': { type: 'npm', name: 'npm:@nx/linter', data: [Object] },
    'npm:@nx/web': { type: 'npm', name: 'npm:@nx/web', data: [Object] },
    'npm:@nx/workspace': { type: 'npm', name: 'npm:@nx/workspace', data: [Object] },
    'npm:@schematics/angular': { type: 'npm', name: 'npm:@schematics/angular', data: [Object] },
    'npm:@types/jest': { type: 'npm', name: 'npm:@types/jest', data: [Object] },
    'npm:@types/node': { type: 'npm', name: 'npm:@types/node', data: [Object] },
    'npm:@typescript-eslint/eslint-plugin': {
      type: 'npm',
      name: 'npm:@typescript-eslint/eslint-plugin',
      data: [Object]
    },
    'npm:@typescript-eslint/parser': {
      type: 'npm',
      name: 'npm:@typescript-eslint/parser',
      data: [Object]
    },
    'npm:cypress': { type: 'npm', name: 'npm:cypress', data: [Object] },
    'npm:eslint': { type: 'npm', name: 'npm:eslint', data: [Object] },
    'npm:eslint-config-prettier': { type: 'npm', name: 'npm:eslint-config-prettier', data: [Object] },
    'npm:eslint-plugin-cypress': { type: 'npm', name: 'npm:eslint-plugin-cypress', data: [Object] },
    'npm:jest': { type: 'npm', name: 'npm:jest', data: [Object] },
    'npm:jest-environment-jsdom': { type: 'npm', name: 'npm:jest-environment-jsdom', data: [Object] },
    'npm:jest-preset-angular': { type: 'npm', name: 'npm:jest-preset-angular', data: [Object] },
    'npm:jsonc-eslint-parser': { type: 'npm', name: 'npm:jsonc-eslint-parser', data: [Object] },
    'npm:nx': { type: 'npm', name: 'npm:nx', data: [Object] },
    'npm:prettier': { type: 'npm', name: 'npm:prettier', data: [Object] },
    'npm:ts-jest': { type: 'npm', name: 'npm:ts-jest', data: [Object] },
    'npm:ts-node': { type: 'npm', name: 'npm:ts-node', data: [Object] },
    'npm:tsconfig-paths': { type: 'npm', name: 'npm:tsconfig-paths', data: [Object] },
    'npm:typescript': { type: 'npm', name: 'npm:typescript', data: [Object] }
  },
  dependencies: {
    remote: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object]
    ],
    host: [ [Object], [Object], [Object], [Object], [Object], [Object] ]
  }
}
mfConfig.name remote
Dependencies {
  workspaceLibraries: [],
  npmPackages: [
    '@angular/core',
    '@angular/platform-browser',
    '@angular/router',
    '@angular/common',
    '@angular/platform-browser-dynamic',
    'jest-preset-angular',
    '@nx/angular'
  ]
}
workspaceLibraries []
npmPackages [
  '@angular/core',
  '@angular/platform-browser',
  '@angular/router',
  '@angular/common',
  '@angular/platform-browser-dynamic',
  'jest-preset-angular',
  '@nx/angular'
]
sharedLibraries {
  getAliases: [Function: getAliases],
  getLibraries: [Function: getLibraries],
  getReplacementPlugin: [Function: getReplacementPlugin]
}
DEFAULT_ANGULAR_PACKAGES_TO_SHARE [ '@angular/animations', '@angular/common' ]
dependencies.npmPackages [
  '@angular/core',
  '@angular/platform-browser',
  '@angular/router',
  '@angular/common',
  '@angular/platform-browser-dynamic',
  'jest-preset-angular',
  '@nx/angular'
]
npmPackages {
  '@angular/animations': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/animations/browser': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common/upgrade': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/core': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/core/rxjs-interop': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/core/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser/animations': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/router': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/router/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/router/upgrade': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser-dynamic': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser-dynamic/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  'jest-preset-angular': { singleton: true, strictVersion: true, requiredVersion: '13.1.1' },
  '@nx/angular': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' },
  '@nx/angular/mf': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' },
  '@nx/angular/module-federation': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' },
  '@nx/angular/testing': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' }
}
sharedDependencies apps/remote {}
sharedDependencies {
  '@angular/animations': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/animations/browser': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common/http': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/common/upgrade': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/core': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/core/rxjs-interop': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/core/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser/animations': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/router': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/router/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/router/upgrade': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser-dynamic': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  '@angular/platform-browser-dynamic/testing': { singleton: true, strictVersion: true, requiredVersion: '16.0.1' },
  'jest-preset-angular': { singleton: true, strictVersion: true, requiredVersion: '13.1.1' },
  '@nx/angular': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' },
  '@nx/angular/module-federation': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' },
  '@nx/angular/testing': { singleton: true, strictVersion: true, requiredVersion: '16.2.2' }
}

I guess something has changed when it comes to generating the Project graph: image

So obviously something is wrong with the project graph. Think I need som help here @Coly010 ! 🙏

I can confirm this issue is happening with Nx version 18.0.4 with a module federation project setup.

image

Buenas, he tenido el mismo problema, la solución ha sido actualizar las dependencias del proyecto a la última en su momento

image

image

El hecho es que tengo una librería desarrollada en V17 y me estaba dando este error.

Actualización [27/04/2024]

La actualización no funcionó

SOLUCIONADO Coloqué en el proyecto que consumirá la librería la siguiente propiedad en el angular.json y funcionó

“preserveSymlinks”: true

Same issue on 18.0.0

 >  NX   Report complete - copy this into the issue template

   Node   : 18.16.1
   OS     : win32-x64
   npm    : 9.5.1

   nx                 : 18.0.0
   @nx/js             : 18.0.0
   @nx/jest           : 18.0.0
   @nx/linter         : 18.0.0
   @nx/eslint         : 18.0.0
   @nx/workspace      : 18.0.0
   @nx/angular        : 18.0.0
   @nx/cypress        : 18.0.0
   @nx/devkit         : 18.0.0
   @nx/eslint-plugin  : 18.0.0
   @nx/storybook      : 18.0.0
   @nrwl/tao          : 18.0.0
   @nx/web            : 18.0.0
   @nx/webpack        : 18.0.0
   typescript         : 5.3.3
   ---------------------------------------
   Community plugins:
   @storybook/angular    : 7.6.8
   @wks/forms-schematics : 0.0.14
   nx-htmlhint           : 1.0.3```

I even tried to use the new loadRemoteModule from @nx/angular/mf following this guide: https://nx.dev/recipes/angular/dynamic-module-federation-with-angular

But I still get the same error:

core.mjs:11458 ERROR Error: Uncaught (in promise): Error: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.io/errors/NG0203
Error: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.io/errors/NG0203
    at injectInjectorOnly (core.mjs:731:15)
    at Module.ɵɵinject (core.mjs:744:60)
    at Object._class21_Factory [as useFactory] (router.mjs:425:84)
    at Object.factory (core.mjs:9511:38)
    at core.mjs:9412:43
    at runInInjectorProfilerContext (core.mjs:694:9)
    at R3Injector.hydrate (core.mjs:9411:17)
    at R3Injector.get (core.mjs:9281:33)
    at injectInjectorOnly (core.mjs:738:40)
    at ɵɵinject (core.mjs:744:60)
    at resolvePromise (zone.js:1193:31)
    at resolvePromise (zone.js:1147:17)
    at zone.js:1260:17
    at _ZoneDelegate.invokeTask (zone.js:402:31)
    at core.mjs:10655:55
    at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:10655:36)
    at _ZoneDelegate.invokeTask (zone.js:401:60)
    at Object.onInvokeTask (core.mjs:10968:33)
    at _ZoneDelegate.invokeTask (zone.js:401:60)
    at Zone.runTask (zone.js:173:47)

I’ve added that repro here: https://github.com/JonWallsten/nx-repro/tree/dynamic