Angular注入链移至库后失效,求Angular 17修复方案
场景还原
在名为app-standalone的Angular 17独立应用中,将CoreService、OuterService、OutmostService组成注入链并在AppComponent中使用,运行完全正常:
import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class CoreService { constructor() { console.log("Initialized Core"); } } @Injectable({ providedIn: 'root' }) export class OuterService { constructor(private core: CoreService) { console.log("Initialized Outer"); } } @Injectable({ providedIn: 'root' }) export class OutmostService { constructor(private outer: OuterService) { console.log("Initialized Outmost"); } } @Component({ selector: 'app-root', standalone: true, imports: [CommonModule, RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { title = 'app-standalone'; constructor(private outmost: OutmostService){ console.log("Initialized AppComponent"); } }
随后将CoreService、OuterService移至名为lib-core的Angular库中:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class CoreService { constructor() { console.log("Initialized Core"); } } @Injectable({ providedIn: 'root' }) export class OuterService { constructor(private core: CoreService) { console.log("Initialized Outer"); } }
创建使用该库的新独立应用app-uses-lib-core:
import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; import { Injectable } from '@angular/core'; import { OuterService } from 'lib-core'; @Injectable({ providedIn: 'root' }) export class OutmostService { constructor(private outer: OuterService) { console.log("Initialized Outmost"); } } @Component({ selector: 'app-root', standalone: true, imports: [CommonModule, RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { title = 'app-uses-lib-core'; constructor(private outmost: OutmostService){ console.log("Initialized AppComponent"); } }
运行新应用时触发运行时错误:
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.
问题原因
核心原因是Angular库的构建配置不完整,导致独立应用无法正确识别库中服务的注入上下文:
- 库的
public-api.ts未正确导出服务,应用无法正确解析库中的服务符号; - 库的
package.json缺少必要的Angular peer依赖配置,或未配置ng-packagr构建规则,导致构建产物无法被Angular注入系统识别; - 库构建后,服务的注入元数据未被正确保留,Angular无法将其注册到根注入器中,触发注入上下文错误。
修复步骤
1. 完善库的public-api.ts导出
在lib-core/projects/lib-core/src/public-api.ts中添加服务导出:
export { CoreService, OuterService } from './lib/lib-core.service';
2. 修正库的package.json配置
确保package.json包含正确的peer依赖和ng-packagr配置:
{ "name": "lib-core", "version": "0.0.1", "peerDependencies": { "@angular/common": "^17.0.0", "@angular/core": "^17.0.0" }, "dependencies": { "tslib": "^2.3.0" }, "ngPackage": { "dest": "../../dist/lib-core", "lib": { "entryFile": "src/public-api.ts" } } }
3. 重新构建库
执行构建命令生成正确的库产物:
ng build lib-core
4. 验证应用依赖引用
确保app-uses-lib-core的package.json中正确引用本地构建的库:
"dependencies": { "lib-core": "file:../dist/lib-core" }
重新安装依赖:
npm install
可选:显式注册服务(若仍有问题)
如果上述步骤后仍报错,可在AppComponent的装饰器中显式提供库服务,确保注入上下文正确:
@Component({ selector: 'app-root', standalone: true, imports: [CommonModule, RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.scss', providers: [OuterService] })
修复后运行应用,控制台应输出正确的初始化顺序:
Initialized Core → Initialized Outer → Initialized Outmost → Initialized AppComponent
内容的提问来源于stack exchange,提问作者Mako

