Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most modern way to externalize Angular 2 environment configuration?

I'm curious what the most modern way, as of April 2017, to build an Angular 2 app for deployment with external configuration?

Following the Build Once Deploy Anywhere philosophy I'd like to figure out how to package my Angular 2 app as a Docker image that I can drop onto any server and configure from outside.

I've done this fairly simple with most other components of this application including a Spring Boot backend, but the best way to do this with Angular 2 is hard to pin down since the framework evolved so massively between beta releases that a lot of information is out-of-date.

I've got Angular 2.4.9 with NPM for package management running in a Node Docker container as a JIT app with specific environment.ts baked into the image at build-time. I'd like to get the size and speed advantages of AoT compilation as well as eventual minification and other download size enhancements, but AoT bakes the contents of an environment.ts file directly into main.bundle.js so there's no way at all to change it after ng build

The Angular2-webpack-starter project seems very out-of-date and is mutually exclusive with Angular-CLI anyway, but it's got this method here which seems to setup config/webpack.ENV.js files that refer to OS environment variables. I feel like environment variables are a bit overly complicated for a lot of apps, but it's better than nothing. But how can I apply this in Angular-CLI terms, or is there a better way?

As I understand it Angular-CLI abstracts webpack too heavily to directly access the webpack and plugin configs to follow this approach. But could I just reference process.env in my environment.ts and Bob's your uncle or is it more complicated than that?

Do I need to crack open main.bundle.js and rewrite the bits between var environment = { and //# sourceMappingURL=environment.js.map? That seems needlessly hacky for something as popular as Angular.

like image 919
Sloloem Avatar asked Apr 05 '17 14:04

Sloloem


People also ask

How do you create an angular app once and deploy it to multiple environments?

All we have to do is: Add a JSON configuration file in the src folder. Update our angular/webpack configuration to include the file in our dist folder. Add a simple configuration service with a call to get our config data from our config file.

How angular manage multiple environments CLI?

Adding multiple environments:Open your angular project in a preferred IDE. Navigate to src>environments, there you can see two files environment. ts and environment. prod.

Do we need to set environment variables for angular?

If you're building an app that uses an API, you'll want to use your API key for testing environments during development and your API key for live environments during production. In Angular, you can create environment variables with the environment.

Where do you put environmental variables in angular project?

Angular provides build-in support to configure and manage Environment Variables. It keeps the environment configuration under the folder src/environments folder.


1 Answers

If you really must build once and deploy the same build artifact multiple times then one solution (although in my opinion is a bit of a hack) is to put your external configuration inside 'assets' folder then make an ajax call from environment.ts to read the values:

src/environments/environment.ts:

export const environment = new Promise((resolve, reject) => {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', './assets/environment.json');
  xhr.onload = function () {
    if (xhr.status === 200) {
      resolve(JSON.parse(xhr.responseText));
    }
    else {
      reject("Cannot load configuration...");
    }
  };
  xhr.send();
});

src/assets/environment.json:

{
  "production": false,
  "some_api_url": "https://dev_url"
}

You also need to postpone module bootstrapping to when ajax call is completed:

src/main.ts:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment as environmentPromise } from './environments/environment';

environmentPromise.then(environment => {

  if (environment["production"]) {
    enableProdMode();
  }

  platformBrowserDynamic().bootstrapModule(AppModule);
});

Working sample here: https://github.com/mehradoo/angular-external-cfg/commit/0dd6122a0d8ff100c23458807cc379e9e24cc439

like image 58
Mehrad Sadegh Avatar answered Oct 04 '22 00:10

Mehrad Sadegh