9

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?

Ole Spaarmann
  • 15,845
  • 27
  • 98
  • 160

2 Answers2

4

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:

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:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • But that would mean that I have to copy and paste in the right configuration depending on the environment. I think it would be more elegant if I had a config file for each environment, which are out of version control and could be individual for each team member. Copy & pasting before build also seems not such a great idea if you want to have an automatic flow and CI. – Ole Spaarmann Mar 31 '16 at 14:32
  • 1
    It would be no manual copy / paste but integrated within your build (with gulp and gulp-html-replace for example). See this question: http://stackoverflow.com/questions/36285064/how-do-i-actually-deploy-an-angular-2-typescript-systemjs-app/36315060 – Thierry Templier Mar 31 '16 at 14:55
  • 1
    Another approach would be to boostrap the application after having loading a configuration file. I updated my answer accordingly... – Thierry Templier Mar 31 '16 at 15:00
  • 1
    If you're using angular cli and just have to distinguish dev vs prod, maybe you could use built-in `environment.ts` and `environment.prod.ts`, one of which is injected into the app depending on whether you `ng build --dev` or `ng build --prod` – yannick1976 Feb 17 '18 at 11:04
0

Maybe you should try Grunt. Example: http://mindthecode.com/how-to-use-environment-variables-in-your-angular-application/

Rozzy
  • 11
  • 2
  • This is a good hint. I'm using Gulp though, but there is something similar [here](https://www.npmjs.com/package/gulp-ng-constant). I just have to find out if it plays nicely with Angular 2 – Ole Spaarmann Mar 31 '16 at 14:37