Using environment variables in Angular applications

By default, Angular only provides the NODE_ENV variable when building the application. You may use process.env.NODE_ENV anywhere in your TS/JS source, and the build will inline this value in the output chunks.

Other variables, such as those prefixed by NX_ will not work in Angular. To add support for other environment variables, do the following.

First, install @types/node so we can use process.env in our code.

npm install --save-dev @types/node

# Or with yarn
yarn add --dev @types/node

Next, update the build and serve targets (in project.json or angular.json file), to the following.

1{
2  "build": {
3    // NOTE: change the executor to one that supports custom webpack config.
4    "executor": "@nrwl/angular:webpack-browser",
5    // snip
6    "options": {
7      // NOTE: This file needs to be created.
8      "customWebpackConfig": {
9        "path": "apps/myapp/webpack.config.js"
10      }
11      // snip
12    }
13  },
14  "serve": {
15    // NOTE: use dev-server that supports custom webpack config.
16    "executor": "@nrwl/angular:webpack-server"
17    // snip
18  }
19}
20

Then, we can use DefinePlugin in our custom webpack.

1// apps/myapp/webpack.config.js
2const webpack = require('webpack');
3
4function getClientEnvironment(configuration) {
5  // Grab NODE_ENV and NX_* environment variables and prepare them to be
6  // injected into the application via DefinePlugin in webpack configuration.
7  const NX_APP = /^NX_/i;
8
9  const raw = Object.keys(process.env)
10    .filter((key) => NX_APP.test(key))
11    .reduce(
12      (env, key) => {
13        env[key] = process.env[key];
14        return env;
15      },
16      {
17        NODE_ENV: process.env.NODE_ENV || configuration,
18      }
19    );
20
21  // Stringify all values so we can feed into webpack DefinePlugin
22  return {
23    'process.env': Object.keys(raw).reduce((env, key) => {
24      env[key] = JSON.stringify(raw[key]);
25      return env;
26    }, {}),
27  };
28}
29
30module.exports = (config, options, context) => {
31  config.plugins.push(
32    new webpack.DefinePlugin(getClientEnvironment(context.configuration))
33  );
34  return config;
35};
36

Now, when we define variables in our .env file, such as...

# apps/myapp/.env
NX_API_URL=http://localhost:3333

Finally, We can use environment variables in our code. For example,

1// apps/myapp/src/main.ts
2import { enableProdMode } from '@angular/core';
3import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
4import { AppModule } from './app/app.module';
5
6if (process.env['NODE_ENV'] === 'production') {
7  enableProdMode();
8}
9
10// This is defined in our .env file.
11console.log('>>> NX_API_URL', process.env['NX_API_URL']);
12
13platformBrowserDynamic()
14  .bootstrapModule(AppModule)
15  .catch((err) => console.error(err));
16

You should also update tsconfig.apps.json and tsconfig.spec.json files to include node types.

1{
2  "extends": "./tsconfig.json",
3  "compilerOptions": {
4    // snip
5    "types": ["node"]
6  }
7  // snip
8}
9

Using environment variables in index.html

While you cannot use variable in index.html, one workaround for this is to create different index.*.html files, such as index.prod.html, then swap it in different environments.

For example in project.json (or angular.json),

1{
2  "build": {
3    "executor": "@angular-devkit/build-angular:browser",
4    // snip
5    "configurations": {
6      "production": {
7        // snip
8        "fileReplacements": [
9          {
10            "replace": "apps/myapp/src/environments/environment.ts",
11            "with": "apps/myapp/src/environments/environment.prod.ts"
12          },
13          {
14            "replace": "apps/myapp/src/index.html",
15            "with": "apps/myapp/src/index.prod.html"
16          }
17        ]
18      }
19    }
20  }
21}
22