In a CI/CD environment the Angular should be configured based on the specific runtime environment.
Initializing the app with data with an initial backend config object is not very secure.
The config data contains urls of services and map tiles. So, no secrets or credentials.
We would like to select an assets config file based on a simple backend result, e.g. an environment string.
Normally initializing aan Angular app is done with app_initalizer. Can this 2 step approach be done, so with the backend environment string load a specific assets config file?
Below you find a solution for building once an Angular app (e.g. inside a NgInx Docker container) and deploy it in any environments. For example 'test', 'production'.
The service for loading the config settings:
@Injectable()
export class AppConfigServiceBasedOnBackendEnvir1 {
private appConfigBasedOnBackend: any;
constructor(private http: HttpClient) { }
async loadAppConfig( environment: string) {
await firstValueFrom( this.http.get('http://localhost:8080/initialsetup1'))
.then(data => {
let result: BackendResult = data as BackendResult;
return this.loadAppConfigDeep( result.environment);
});
}
async loadAppConfigDeep( environment: string) {
await firstValueFrom(this.http.get('/assets/appConfigBasedOnBackend-acc.json'))
.then(data => {
this.appConfigBasedOnBackend = data;
});
}
getConfig() {
return this.appConfigBasedOnBackend;
}
}
The simplified config class:
export class BackendResult {
environment: string = '';
}
And the config for loading the configs dynamically before starting the full blown Angular app in app.Module.ts
const appInitializerDeepAcceptanceFn = (appConfig: AppConfigServiceBasedOnBackendEnvir1) => {
return () => {
return appConfig.loadAppConfig( 'acceptance');
};
};
providers: [ AppConfigServiceBasedOnBackendEnvir1, {
provide: APP_INITIALIZER,
useFactory: appInitializerDeepAcceptanceFn,
multi: true,
deps: [AppConfigServiceBasedOnBackendEnvir1]
}, ...
Any other component using the config data:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
envirBasedOnBackendEnvir1: string = 'nothing-yet-1';
constructor( private appConfigBasedOnBackendEnvir1: AppConfigServiceBasedOnBackendEnvir1) { }
ngOnInit() {
this.envirBasedOnBackendEnvir1 = this.appConfigBasedOnBackendEnvir1.getConfig().config1;
}
}