Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: How to handle app configuration for different environments

Tags:

angular

The following scenario: I build an Angular app which consumes a REST API (that could be built with Elixir or RoR or whatever). During development I want Angular to consume a different API than in production (maybe with test data, maybe because I build the API at the same time and it runs on my machine).

Additionally other members of my team might want to use another local API address. That means this shouldn't go into the version control system.

So for example the api_base_urlcould be http://localhost:4000 for me, http://testapi.local for my colleague and http://api.example.com for production.

The api_base_url value should be available in multiple components.

What is a good approach to handle this?

like image 967
Ole Spaarmann Avatar asked Mar 31 '16 14:03

Ole Spaarmann


1 Answers

You could define a dedicated provider provided these hints. Something like that:

bootstrap(AppComponent, [
  (...)
  provide('configuration', {
    useValue: {
      apiBaseUrl: 'http://localhost:4000'
    }
  }
]);

When you package your code for production, you can replace the file containing this code with the one with the configuration for production.

To take into account this configuration, you can extend the RequestOptions class to prefix all your request with the apiBaseUrl prefix:

import {
  BaseRequestOptions, RequestOptions, RequestOptionsArgs
} from 'angular2/http';

export class AppRequestOptions extends BaseRequestOptions {
  constructor(private @Inject('configuration') configuration:any) {
  }

  merge(options?:RequestOptionsArgs):RequestOptions {
    options.url = this.configuration.apiBaseUrl + options.url;
    return super.merge(options);
  }
}

Don't forget to configure the request options when bootstrapping your application:

bootstrap(AppComponent, [
  (...)
  provide('configuration', {
    useValue: {
      apiBaseUrl: 'http://localhost:4000'
    }
  }
  provide(RequestOptions, { useClass: AppRequestOptions })
]);

This processing could be contained into a dedicated JS file that would be replaced within the build (with gulp and gulp-html-replace for example).

See this question:

  • How do I actually deploy an Angular 2 + Typescript + systemjs app?

For the last step, you could also load asynchronously the application based on a configuration file:

var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
var http = injector.get(Http);

http.get('config.json').map(res => res.json())
  .subscribe(data => {
    bootstrap(AppComponent, [
      HTTP_PROVIDERS
      provide('config', { useValue: data })
    ]);
  });

See this question for more details:

  • How to bootstrap an Angular 2 application asynchronously
like image 55
Thierry Templier Avatar answered Oct 03 '22 07:10

Thierry Templier