Load configuration from external file

Here is the scenario:
I am using angular-cli for my project.
I can use the environment.ts file in the enviroments folder in order to store configuration information in it. for example: my WebApi base address .

Although i am using a separate environment.ts file for production,  this file is part of the build process angular-cli / webpack do while i build the project using “ng build –prod”.

if i need to update the configuration on my test/qa/prod servers, i need to either open the bundeled js files with an editor and find the right line, or return to my source code, make the change and re-build.

Another option, requested in one of my projects  – to store the configuration in an external json file.

How did i accomplish this ?

  • create a config.ts class, that will be the model for the configuration data structure.
    export class Configuration{
       constructor(public webApiBaseUrl: string,
                   public signalrBaseUrl: string)
    
    }
  • create a sample json file that adheres to the config.ts file
  • save this file (e.g. config.json ) in the assets folder . this folder is configured in the angular-cli.json file . This folder is copied as is, during build, into the dist folder. (you could create a seperate config folder as well, and put the file there)
  • in my environment.ts files, add a property to point to this fileexport const environment = {
    production: false,
    configFile: 'assets/config/config.json'
    };
  • now, we need to create a service that will load this configuration.
    @Injectable()
    
    import {Configuration} from './config-model.ts'
    export class ConfigService {
       private config: Configuration;
       constructor(private http:Http) {}
      
      load(url:string) { 
        return new Promise((resolve) => {
          this.http.get(url).map(res=>res.json())
            .subscribe(config => {
              this.config = config;
              resolve();
            });
      }
    
      getConfiguration():Configuration {
    
        return this.config;
      }
    }

    The actual loading – comes next.

  • we want to initialize the service in our AppModule.
    one of the main things we want to make sure: the configuration is loaded ,
    BEFORE any of our components gets rendered, as they might need information from the configuration file.We will use APP_INITIALIZER , which will help us to execute code an the initialization of our angular 2 application.AppModule.tsadd the following

    import { APP_INITIALIZER } from '@angular/core';
    import { HttpModule } from '@angular/http';

    next import our configuration service

    import { ConfigService } from './config.service';

    create a load function. we use this function out of the module, for AOT reasons.

    import { environment } from '../environments/environment';
    
    export function ConfigLoader(configService: ConfigService) {
    //Note: this factory need to return a function (that return a promise)
    
      return () => configService.load(environment.configFile); 
    }
    

    now, the AppModule declaration and metadata

    @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            HttpModule,
            BrowserModule
        ],
        providers: [
            ConfigService,
            {
                provide: APP_INITIALIZER,
                useFactory: ConfigLoader,
                deps: [ConfigService],
                multi:true;
            }],
        bootstrap: [ AppComponent ]
    })
    export class AppModule {
    }
  • now, in our component, for example, we can use the configuration information
    constructor(private configService: ConfigService) {
            //
        }
    
        webApiBaseUrl:string;
        anyMethod() {
            this.webApiBaseUrl = 
                      this.configService.getConfiguration().webApiBaseUrl
        }

    and rest assure, that the value is already loaded into our configService, during initialization, well before we reach this part in our code.

    To Sum up:

    If needed, you can move your configuration (or part of it) into a separate json file
    that will not be part of the bundling process – giving you the ability to change the configuration values in a snap, without a need of a re-build process.

Advertisements

1 thought on “Load configuration from external file”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s