Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass environment variables to an Angular2 app?

I need to pass the backend url to my Angular2 app, since production and dev servers are hosted on different locations.

I know I could store such things in an external config.json and load upon startup. This, however, seems like unnecessary extra call to server before the app can get started.

Alternatively, what I do now is I do create a single global variable, which I inject in gulp depending on build. My app isn't a lib that needs to be reusable I don't believe I should hit unexpected global name clashes. But it's not a good practice.

I wonder if there's a third, better solution?

like image 398
Zlatko Avatar asked Apr 10 '16 10:04

Zlatko


People also ask

Can angular access environment variables?

Introduction. 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.

What is environment TS file in angular?

A project's src/environments/ folder contains the base configuration file, environment. ts , which provides a default environment. You can add override defaults for additional environments, such as production and staging, in target-specific configuration files. For example: myProject/src/environments.


5 Answers

Just put variables inside the environment object.

export const environment = {
  production: false,
  url: 'http://localhost:3000/api'
};

After that, you could import and use it. Angular Cli will swap files automatically.

import { environment } from '../environments/environment';

P.S. Variables are available in environment object.

this.url = environment.url
like image 130
Boris Siscanu Avatar answered Oct 19 '22 22:10

Boris Siscanu


I would see two ways to do that:

  • Leverage a JSON configuration in a file. This file would be loaded before boostrapping the application:

    var app = platform(BROWSER_PROVIDERS)
       .application([BROWSER_APP_PROVIDERS, appProviders]);
    
    var http = app.injector.get(Http);
    http.get('config.json').subscribe((config) => {
      return app.bootstrap(AppComponent, [
        provide('config', { useValue: config })
      ]);
    }).toPromise();
    

    Here is a corresponding plunkr describing the global approach: https://plnkr.co/edit/ooMNzEw2ptWrumwAX5zP?p=preview.

  • Leverage a configuration module:

    export const CONFIG = {
      (...)
    };
    

    that will be imported and included in providers when bootstrapping the application:

      import {CONFIG} from './config';
    
      bootstrap(AppComponent, [
        provide('config', { useValue: CONFIG })
      ]);
    

With the two approaches, configuration can be defined for each environment when packaging the application.

This question could also give you hints about how to package an Angular2 application:

  • How do I actually deploy an Angular 2 + Typescript + systemjs app?
like image 45
Thierry Templier Avatar answered Oct 19 '22 23:10

Thierry Templier


I have been struggling with the above for a while too. And even though Thierry's answer is very good, but I somehow find it too complicated for simply having env vars, so I thought I present my thoughts too.

1) I first created an interface describing my env vars app.settings.ts:

export interface IEnvVars {
    ENV: string;
    API_URL: string;
}

export class AppSettings {
    public static env_vars: IEnvVars;
}

2) I added the JavaScript fetch API type definitions to my .d.ts file. (Not absolutely needed if you don't mind having fetch as unresolved, but I did mind it, so added the types)

3) So now in my main.ts I can make a call to the endpoint that returns the environment variables:

import {bootstrap}    from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {AppSettings,IEnvVars} from "./configs/app.settings";
import {enableProdMode} from "angular2/core";

fetch('/env-vars', {method: 'get'}).then((response) => {
    response.json().then((env_vars:IEnvVars) => {
        AppSettings.env_vars = env_vars;
        if (AppSettings.env_vars.ENV != 'development') enableProdMode();
        bootstrap(AppComponent);
    });
});

So now I access my env vars in any service or component simply by:

import {AppSettings} from "../configs/app.settings";

so within a method etc. you could go like:

let customersURL = `${AppSettings.env_vars.API_URL}/customers`;

Please note that you may need polyfills for fetch API as Safari and IE still don't support this. (Link to polyfill exampel)

like image 22
Ali Habibzadeh Avatar answered Oct 19 '22 21:10

Ali Habibzadeh


I think this might be useful to you. Passing asp.net server parameters to Angular 2 app

This way you can inject any value from html page (which can get value from the server, like current environment variable)

like image 28
ravi punjwani Avatar answered Oct 19 '22 23:10

ravi punjwani


Not only the URL but there are some other parameters that need to be taken from environment variables.

Environment variables must be taken and written to environment.ts before build! because of some Javascript restrictions in accessing filesystem, environment, etc at runtime.

For this, first you need a module for writing environment variables and this module has to be executed with ts-node in your build script:

"scripts": {
  .....
  "config": "ts-node set-env.ts",
  "build": "npm run config && ng build",
  ....
},

and your set-env.ts file:

var fs = require('fs');
const targetPath = './src/environments/environment.ts';
const colors = require('colors');
require('dotenv').load();
const envConfigFile = `export const environment = {
  ENV_VAR_1: '${process.env.var_1}',
  ENV_VAR_n: '${process.env.var_n}',
};`;
console.log(colors.magenta('The content of `environment.ts` will be: \n'));
console.log(colors.grey(envConfigFile));
fs.writeFile(targetPath, envConfigFile, function (err) {
  if (err) {
    throw console.error(err);
  } else {
    console.log(colors.magenta(`environment.ts file is created`));
  }
});

and of course you have to add ts-node and dotenv to your dependencies.

and you can easily access variables of environemnt.ts like:

import {environment} from '../environments/environment';
....
var envVar1 = environment.ENV_VAR_1;

Node 12^, Angular 10^, and I didn't check this with older Node/Angular/Typescrip versions

like image 45
nil Avatar answered Oct 19 '22 23:10

nil