Как мне сослаться на мою конфигурацию в моем импорте?
Я добавил в свой проект AngularFire. В его ридми мне было сказано добавитьAngularFireModule.initializeApp(...)
к импорту моего AppModule
Однако в примерах люди используют константу среды, это не вариант, потому что для развертывания требуется файл конфигурации, в котором он будет заменять переменные при развертывании в зависимости от среды, в которой развертывается.
Я считаю, что моя конфигурация загружается после импорта, что означает, что ничего не передается в .initializeApp(...)
app.module.ts
import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
...
export function initializeApp(appConfig: AppConfig) {
return () => appConfig.load();
}
@NgModule({
declarations: [
AppComponent
],
imports: [
...,
AngularFireModule.initializeApp(AppConfig.firebase),
AngularFireAuthModule
],
providers: [
AppConfig,
{ provide: APP_INITIALIZER, useFactory: initializeApp, deps: [AppConfig], multi: true },
...,
],
bootstrap: [AppComponent]
})
export class AppModule { }
app-config.ts
import { Injectable } from '@angular/core';
import { AppConfigModel } from './shared/models/app-config.model';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';
/**
* This config pattern based off https://devblogs.microsoft.com/premier-developer/angular-how-to-editable-config-files/
* which is referenced in Octopus Deploy blog here https://octopus.com/blog/javascript-configuration
*/
@Injectable()
export class AppConfig extends AppConfigModel {
constructor(private http: HttpClient) {
super();
}
/**
* Loads the required config file from assets, depending on configName of environment.
* This allows replacement of variables by Octopus Deploy
*/
public load() {
const jsonFile = `assets/config/config.${environment.configName}.json`;
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile).toPromise().then((response: AppConfigModel) => {
this.mapConfigToProperties(response);
resolve();
}).catch((response: any) => {
console.error('On config load', response);
reject(`Could not config load file '${jsonFile}': ${JSON.stringify(response)}`);
});
});
}
private mapConfigToProperties(config: any) {
Object.keys(config).forEach(key => {
AppConfig[key] = config[key];
});
}
}
Я бы очень хотел, чтобы эта проблема была решена без необходимости изменять какие-либо процессы сборки и просто иметь возможность использовать AppConfig
чтобы получить конфигурацию.
package.json
{
...,
"dependencies": {
"@angular/animations": "^6.1.10",
"@angular/cdk": "^6.3.0",
"@angular/common": "^6.0.3",
"@angular/compiler": "^6.0.3",
"@angular/core": "^6.0.3",
"@angular/fire": "^5.3.0",
"@angular/forms": "^6.0.3",
"@angular/http": "^6.0.3",
"@angular/platform-browser": "^6.0.3",
"@angular/platform-browser-dynamic": "^6.0.3",
"@angular/router": "^6.0.3",
"core-js": "^2.5.4",
"firebase": "^7.7.0",
"moment": "^2.24.0",
"ng-pick-datetime": "^6.0.16",
"ng-pick-datetime-moment": "1.0.7",
"ngx-image-cropper": "^2.0.2",
"ngx-smart-modal": "^7.1.1",
"ngx-textarea-autosize": "^2.0.3",
"ngx-toastr": "^10.0.4",
"rxjs": "6.3.3",
"zone.js": "^0.8.26"
},
...
}
main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { FirebaseOptionsToken, AngularFireModule } from '@angular/fire';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
1 ответ
Этого можно добиться, задав параметры для platformBrowserDynamic(...)
который принимает массив поставщиков, аналогичный массиву в providers
свойство @NgModule
.
Мы решим эту проблему с помощью этого параметра. Мы введем параметр для конфигурации firebase, а затем удалим его из импорта в AppModule.
main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { FirebaseOptionsToken, AngularFireModule } from '@angular/fire';
if (environment.production) {
enableProdMode();
}
// Get the config file
fetch(`assets/config/config.${environment.configName}.json`)
.then(response => response.json())
.then((response: any) => {
// Here we add the additional provider
platformBrowserDynamic([{provide: FirebaseOptionsToken, useValue: response.firebaseSettings}])
.bootstrapModule(AppModule)
.catch(err => console.log(err));
}).catch((response: any) => {
console.error('On config load', response);
});
app.module.ts
import { AngularFireModule, FirebaseOptionsToken } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
...
export function initializeApp(appConfig: AppConfig) {
return () => appConfig.load();
}
// initialize app with empty config
const angularFireImport = AngularFireModule.initializeApp({});
// remove the provider that we have provided for in the platforBrowserDynamic
angularFireImport.providers = angularFireImport.providers.filter(
(provider: any) => provider.provide !== FirebaseOptionsToken
);
@NgModule({
declarations: [
AppComponent
],
imports: [
...,
// import the module we constructed above without the provider
angularFireImport,
AngularFireAuthModule
],
providers: [
...,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Этот ответ был вдохновлен запуском приложения AngularFire2 в конфликтах модулей с данными динамической конфигурации
Дополнительное чтение о провайдерах и внедрении угловых зависимостей, ссылка