我最近将我的单个AppModule
拆分为多个模块,现在我正在尝试延迟加载模块并使其使用共享模块中的单例服务。
我按照文档(以及本教程)中提到的步骤操作,创建了一个提供单例服务的共享CoreModule
。但是,当共享模块的某个服务尝试注入任何单一实例服务时,将引发以下异常:
EXCEPTION: Uncaught (in promise): Error: No provider for HttpClientService!
Error: No provider for HttpClientService!
at NoProviderError.BaseError [as constructor] (http://localhost:5000/lib/angular/@angular/core/bundles/core.umd.js:1105:38)
app.module.ts
@NgModule({
imports: [
BrowserModule,
CoreModule.forRoot(),
AppRoutingModule
]
})
export class AppModule { }
app-routing.module.ts
export const routes: Routes = [
{
path: "mailgroups",
loadChildren: "app/mailgroup/mailgroup.module#MailGroupModule" // <-- lazy loading the module
}
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ],
})
export class AppRoutingModule { }
core.module.ts
(共享模块)
export class CoreModule {
constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error("CoreModule is already loaded. Import it in the AppModule only!");
}
}
static forRoot(): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
HttpClientService, // <-- singleton service 1
UserService // <-- singleton service 2
]
};
}
}
mailgroup.module.ts
(延迟加载模块)
@NgModule({
imports: [
MailGroupRoutingModule
]
})
export class MailGroupModule { }
有趣的是,当我将共享模块CoreModule
导入延迟加载的模块MailGroupModule
时,我没有得到任何异常(尽管构造函数中throw new Error(...)
),因为parentModule
参数总是null
。
我在这里错过了一些明显的东西吗?(省略了我认为不必要的声明)
经过几个小时的"随机"编程,同时拔掉我的头发,我的努力得到了回报。问题出在配置错误的system.config.js
中。
将 SystemJS 配置与文档中使用的systemjs.config.web.js
进行比较时,我注意到在我的文件中配置应用程序文件夹和引导应用程序的文件的路径的方式存在细微差异。
✘ 之前(系统JS配置错误)
System.config({
paths: { ... },
map: {
app: '/app', // <-- This line (incorrect)
...
},
packages: {
app: {
main: '/main.js' // <-- And this line (incorrect)
defaultExtension: 'js'
}
}
})
请注意app: '/app'
中的前导斜杠和main: '/main.js'
中的相对路径。
✔ 之后(正确的SystemJS配置)(
更改为app: 'app'
和main: './main.js'
)
System.config({
paths: { ... },
map: {
app: 'app', // <-- This line (correct)
...
},
packages: {
app: {
main: './main.js' // <-- And this line (correct)
defaultExtension: 'js'
}
}
})
所以,这两个微妙的修复使世界变得不同!
现在,尝试将共享模块导入CoreModule
除AppModule
以外的任何位置,也会导致引发异常,正如预期的那样。
根据最佳实践,核心模块是 AppModule 的扩展。 它不应该是一个共享模块。 它只能由应用模块导入和使用 一个共享模块,应该被调用.....共享模块