Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime Configuration for Angular 6+ Applications

What is the recommended best practice for loading environment specific configuration during runtime of an Angular application? The Angular documentation mentions the use of APP_INITIALIZER, but that is still not early enough in the load process for things such as runtime configuration of imported modules that make use of the .forRoot() convention.

In my use case, I have an authentication service built and imported via a Core module, which is imported by the App module. The authentication library I am using (the angular-oauth2-oidc library) allows for configuration of the automatic appending of access tokens during when importing the module (see this segment). Since there are constraints in the build environment I am working with that only allows me to produce one common build package to deploy to all environments, I am unable to dynamically set values by using different environment.ts files.

One initial idea is to use the fetch API on the index.html page to load a JSON file containing the configuration onto a global variable, but since the call is asynchronous, there is a chance the configuration will not be fully loaded when the import of the Core module occurs.

like image 443
user10252946 Avatar asked Aug 21 '18 05:08

user10252946


People also ask

What is run time in Angular?

The Angular has the environment variables where you can keep the runtime settings, but it has limitations. The setting of the environment variables are defined at build time and cannot be changed at run time. We can keep the configuration information in a database.

What is compile time and runtime in Angular?

Compile-time is the time at which the source code is converted into an executable code while the run time is the time at which the executable code is started running. Both the compile-time and runtime refer to different types of error.

What is a runtime configuration?

A runtime configuration provides the environment in which an application is started, defined by the database server and database of the application. By specifying multiple runtime configurations, the same application can be started on multiple environments, for example for development and testing purposes.

What is configuration in Angular?

A file named angular. json at the root level of an Angular workspace provides workspace-wide and project-specific configuration defaults for build and development tools provided by the Angular CLI. Path values given in the configuration are relative to the root workspace folder.

How do I create and use runtime configuration in angular?

In this article, we learned how to create and runtime configuration and use it in an angular application. We use the injection token APP_INITIALIZER provided by Angular to hook into the Angular initialization process and read the config file. The config file is in JSON format and stored in the src/app/assets/config folder.

Is it possible to change the Uri at runtime in angular?

I would like to be able to change the URI by loading a configuration file at runtime, as opposed to build time (i.e. not using environment.ts). After reading Runtime environment configuration with Angular, this seems like a reasonable approach. Default configuration for local development that will be overridden on deployment

Which file type is used by default in angular?

File environment.ts is used by default. To use other files you should open angular.json and configure fileReplacements section in build configuration and add target blocks to serve and e2e configurations.

What is compile-time configuration in angular?

It basically means that you compile your configuration into your app, at the time when you compile and bundle it. If you’re using the Angular CLI there’s already a preconfigured setup for having such compile-time configuration options. Inside the environments folder you have a environment.ts and environment.prod.ts file.


1 Answers

This was part of my config setup to bring my app through the build pipeline and took me days. I ended up in a solution using the APP_INITIALIZER loading a REST service and build a AppConfigService for my App. I am using the same angular-oauth2-oidc library.

My Solution for this issue was not to setup the OAuthModule in its forRoot() method. It is called before any configs via APP_INITIALIZER are available - this results in undefined values when applied to the config object given to the forRoot() Method.

But we need a token in the http header. So I used a http interceptor for the attaching of the token like described here. The trick is to setup the OAuthModuleConfig in the factory. Obviously this is called after the app is initialized.

Configure Module

@NgModule({
  imports: [
    // no config here
    OAuthModule.forRoot(),
  ],
  providers: [
   {
    provide: HTTP_INTERCEPTORS,
    useFactory: authenticationInterceptorFactory,
    deps: [OAuthStorage, AuthenticationErrorHandler, OAuthModuleConfig],
    multi: true
   }
 ]
})

Factory for interceptor

const authenticationInterceptorFactory = (oAuthService: OAuthStorage, authenticationErrorHandler: AuthenticationErrorHandler, oAuthModuleConfig: OAuthModuleConfig) => {
const config = {
 resourceServer: {
  allowedUrls: [
   // Include config settings here instead
   AppConfigService.settings.apiURL,
   AppConfigService.settings.anotherApiURL,
  ]
  sendAccessToken: true
 },
}
return new AuthenticationInterceptor(oAuthService, authenticationErrorHandler, config);
};
like image 83
vaci Avatar answered Oct 27 '22 07:10

vaci