AppModule加载之前的角加载外部配置 [英] Angular load external configuration before AppModule loads
问题描述
请考虑以下情形(Angular v7):
Consider the following scenario (Angular v7):
- 从外部端点(JSON)加载配置参数(API服务器URL和Auth服务器URL),在加载AppModule之前
- 将配置传递给AppModule(OAuth2模块)
- 使用AOT编译应用程序
- Load configuration parameters (API server URL and Auth server URL) from an external endpoint (JSON), before the AppModule is loaded
- Pass configuration to AppModule (OAuth2 module)
- Compile the app with AOT
第2点在这里很关键,看起来像这样:
Point 2 is key here, and looks like this:
@NgModule({
imports: [
...
OAuthModule.forRoot({
resourceServer: {
allowedUrls: [API_SERVER_URL], // <== we need to set the value that we loaded from the external endpoint (JSON) here
sendAccessToken: true
}
}),
...
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
我已经尝试的东西:
- 具有 APP_INITIALIZER 的解决方案.这不起作用,因为
OAuthModule.forRoot()
在APP_INITIALIZER
可以下载外部配置JSON之前被触发. - 在
main.ts
中使用异步功能将配置加载到Angular环境变量中,然后启动AppModule.由于main.ts
中的import { AppModule } from './app/app.module';
语句,它也不起作用,这会导致AppModule在加载外部配置之前加载并触发OAuthModule.forRoot()
(在main.ts
中动态加载AppModule ,因此无需在顶部放置import
语句. 这是该注释中给出的StackBlitz示例. 它有效,但是1)打破了延迟加载WARNING in Lazy routes discovery is not enabled.
,而2)不适用于AOT编译.它确实很符合我的需求.
- A solution with APP_INITIALIZER. This doesn't work, as the
OAuthModule.forRoot()
is triggered before theAPP_INITIALIZER
can download the external configuration JSON. - Load the config with an async function in the
main.ts
into the Angular environment variables, then bootstrap the AppModule. Also doesn't work due to theimport { AppModule } from './app/app.module';
statement inmain.ts
, which causes the AppModule to load and fireOAuthModule.forRoot()
before the external config is loaded (this comment confirms this behavior). - Load the AppModule dynamically in
main.ts
, so without theimport
statement on top. This is the StackBlitz example given in that comment. It works, but 1) breaks lazy loadingWARNING in Lazy routes discovery is not enabled.
and 2) doesn't work with AOT compiling. It does come very close to what I need.
好奇地想知道是否有人在 AppModule加载之前知道加载外部配置的另一种方法.
Curious to hear if someone is aware of another method to get external configuration loaded before the AppModule loads.
选项3的StackBlitz(动态加载AppModule): https://stackblitz.com/edit/angular -n8hdty
StackBlitz for option 3 (Load the AppModule dynamically): https://stackblitz.com/edit/angular-n8hdty
推荐答案
Angular文档有一章很好,称为NgModule FAQs,其中包含以下部分:
Angular documentation has a great chapter called NgModule FAQs which contains the following section:
如果两个模块提供相同的服务怎么办?
...
如果NgModule A为令牌"X"提供服务并导入 NgModule B,它也为令牌"X"提供服务,然后是NgModule A的服务定义获胜".
If NgModule A provides a service for token 'X' and imports an NgModule B that also provides a service for token 'X', then NgModule A's service definition "wins".
换句话说,您可以在AppModule中为您的库覆盖OAuthModuleConfig:
In other words, you can override OAuthModuleConfig for your library in AppModule:
main.ts
(async () => {
const response = await fetch('https://api.myjson.com/bins/lf0ns');
const config = await response.json();
environment['allowedUrls'] = config.apiBaseURL;
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
})();
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { OAuthModule, OAuthModuleConfig } from 'angular-oauth2-oidc';
import { HttpClientModule } from '@angular/common/http';
import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
OAuthModule.forRoot(),
],
providers: [
{
provide: OAuthModuleConfig,
useFactory: () => ({
resourceServer: {
allowedUrls: [environment['allowedUrls']],
sendAccessToken: true
}
})
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
请注意,我们也应该使用useFactory
而不是useValue
,这样我们就不必依赖导入AppModule
的时间.
Note that we should also use useFactory
instead of useValue
so we don't depend on when AppModule
is imported.
这篇关于AppModule加载之前的角加载外部配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!