【问题标题】:NullInjectorError: R3InjectorError(AppModule)[Router -> Router -> Router]: NullInjectorError: No provider for RouterNullInjectorError: R3InjectorError(AppModule)[Router -> Router -> Router]: NullInjectorError: No provider for Router
【发布时间】:2020-09-29 09:20:26
【问题描述】:

我有一个已发布的库,其中包含一个在其模板中使用 [routerLink] 的组件。在我的应用程序中安装库后,我收到错误 NullInjectorError: R3InjectorError(AppModule)[Router -> Router -> Router]: NullInjectorError:没有路由器的提供者!

在库中的模块中,RouterModule 被导入,如下所示:

@NgModule({
  declarations: [
    Component
  ],
  exports: [
    Component
  ],
  imports: [
    CommonModule,
    RouterModule,
    TranslateModule
  ]
})
export class LibWithComponentModule {
}

在我的应用程序中,RouterModule 配置如下:

const routes: Routes = [{
  path: '',
  component: RootComponent
}];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

app.module.ts 看起来像这样:

  declarations: [
    AppComponent,
    RootComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    LibWithComponentModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

但我认为RouterModule 会被提供?我做错了什么?

【问题讨论】:

  • 可以把路由文件LibWithComponentModule的代码贴出来吗?
  • 没有路由文件,我只是在 LibWithComponent 中使用 [routerLink] 指令。
  • 对于一个库,如果它打算被导入到现有的应用程序中,通常情况下,你不应该导入浏览器模块,而是使用通用模块。还应使用 forchild 导入 Routermodule。 Forroot 仅适用于根模块。
  • 在这种情况下,我只需要路由器模块提供的模板指令,不多也不少,所以我根本不使用 forChild。会不会是这个问题?
  • 不,使用 forChild 似乎不是问题解决者。现在构建库失败并显示消息:装饰器中不支持函数调用,但调用了“RouterModule”。

标签: angular


【解决方案1】:

我正面临与您在我正在处理的大型应用程序中描述的完全相同的情况。我的主应用程序导入了一个已发布的 npm 组件包,其中包含一个利用 routerLink 指令的组件。运行应用程序时,我遇到了您提到的相同的R3InjectorError,即使RouterModule 肯定已正确导入到所有需要它的模块中。

在我的情况下,问题的根本原因是这个 npm 包明确将@angular/router 列为dependencies 之一,而不是peerDependency(在库的情况下它应该是)。这意味着@angular/router 将同时安装在您的node_modulesnode_modules/LIBRARY/node_modules 中!

发生的情况是,在运行时,您发布的组件使用的RouterModule 与您的应用程序使用RouterModule.forRoot() 提供的InjectionToken 具有不同的InjectionToken。已发布组件的RouterModule 引用node_modules/LIBRARY_NAME/node_modules/@angular/router,而主应用程序提供了node_modules/@angular/router 中的那个。

因此,总而言之:解决方法是不要将库中的任何 @angular 包明确列为 dependency,而是将它们正确标记为 peerDependency。这是 an interesting read 管理来自 ng-packagr 文档的依赖项。

供参考:我不确定这是否与 Ivy 完全相关,但在我的场景中,我运行的是启用了 Ivy 的 Angular 11。

在这种情况下,错误消息肯定非常令人困惑,因为注入的服务被命名为 Router 两次,即使它们引用了不同的实例。

希望这也能解决您的问题,我花了相当长的时间来解决这个问题!

【讨论】:

  • 我们正在使用 Bit,我们可以在其中预览我们的 Angular 包。 “预览”(“组合”)包的父模块需要导入“RouterModule”并使用“RouterModule.forRoot([])”进行实例化
【解决方案2】:

我在使用@angular/router 的服务中遇到了同样的错误。我能够通过替换来修复它

@Injectable()

@Injectable({
  providedIn: 'root'
})

在服务类中。

【讨论】:

    【解决方案3】:

    HttpClient 导入您的 .service.ts

    import { HttpClient } from '@angular/common/http';
    

    HttpClientModule 导入 app.module.ts 并将 HttpClientModule 添加到导入数组

    import { HttpClientModule } from '@angular/common/http';
    
     imports: [
        BrowserModule,
        AppRoutingModule,
        HttpClientModule
      ],
    

    【讨论】:

      【解决方案4】:

      对我来说,问题有点像@NilsTitjgat explained,但我不得不将库保留为dependency

      如果您像我一样必须这样做,那么问题出在您的应用程序导入了另一个版本的库,而该版本已导入到该库中。

      如果

      主应用程序

      "dependencies": { 
        "@my/lib": "1.0.0",
        "@another/lib": "1.0.0" 
      }
      

      @my/lib

      "dependencies": { 
        "@another/lib": "1.2.0"  // <-- The version is higher
      }
      

      那么你将面临同样的错误。 解决此问题的方法是将@another/lib 版本从MainApp 升级为1.0.01.1.0

      是的,你不应该这样导入它。如果可以的话,把它放在@NilsTitjgat 提到的peerDependencies

      【讨论】:

        猜你喜欢
        • 2019-01-14
        • 2021-10-16
        • 2021-05-20
        • 1970-01-01
        • 2022-12-27
        • 2022-11-25
        • 1970-01-01
        • 2021-07-02
        • 1970-01-01
        相关资源
        最近更新 更多