Skip to content

Managing Environment Configurations in Angular 15+ Projects

Problem Statement

When creating new Angular projects with Angular CLI 15+, developers notice the environments folder (src/environments) is no longer generated by default. This folder previously contained essential configuration files (environment.ts, environment.prod.ts) for managing environment-specific settings like API endpoints and feature flags. Without this setup, developers must manually configure environment management for their applications.

The change reflects Angular's move toward simplified project structure, but leaves developers needing guidance on environment configuration best practices.

Use ng generate environments

Angular CLI 15.1+ introduced a dedicated schematic to generate environment files with proper configuration:

bash
ng generate environments

This command:

  1. Creates the src/environments folder
  2. Generates environment.ts (default)
  3. Creates environment.prod.ts (production)
  4. Updates angular.json with correct file replacements

Generated Folder Structure

src/
└── environments/
    ├── environment.ts       # Development configuration
    └── environment.prod.ts  # Production configuration

Environment File Content

Each environment file exports a constant object:

typescript
export const environment = {
  production: false,
  apiUrl: 'https://dev.api.example.com'
};
typescript
export const environment = {
  production: true,
  apiUrl: 'https://api.example.com'
};

Automatic angular.json Configuration

The CLI updates your workspace configuration:

json
"configurations": {
  "production": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ],
    // ... other production settings
  }
}

TIP

This command supports custom build configurations. For custom environments (e.g., staging), run:

bash
ng generate environments --name=staging

Adding Environments Manually

If you need custom environment setups:

  1. Create the environments folder:
    bash
    mkdir src/environments
  2. Create environment files:
    bash
    touch src/environments/environment.ts \
          src/environments/environment.prod.ts \
          src/environments/environment.staging.ts
  3. Configure file replacements in angular.json:
    json
    "configurations": {
      "production": {
        "fileReplacements": [
          {
            "replace": "src/environments/environment.ts",
            "with": "src/environments/environment.prod.ts"
          }
        ]
      },
      "staging": {
        "fileReplacements": [
          {
            "replace": "src/environments/environment.ts",
            "with": "src/environments/environment.staging.ts"
          }
        ]
      }
    }

WARNING

Manual setup requires careful configuration. Prefer ng generate environments to avoid human error in build configuration.

Alternative: Dynamic Runtime Environments

For projects requiring runtime environment variables (without rebuilds):

  1. Create a build script (build-scripts/env.js):

    javascript
    const fs = require('fs');
    const path = require('path');
    
    const envVars = Object.keys(process.env)
      .filter(key => key.startsWith('NG_APP_'))
      .reduce((acc, key) => ({ ...acc, [key]: process.env[key] }), {});
    
    const fileContent = `(function(window) {
      window.__env = window.__env || {};
      ${Object.entries(envVars)
        .map(([key, value]) => `window.__env.${key} = ${JSON.stringify(value)};`)
        .join('\n')}
    })(this);`;
    
    fs.writeFileSync(
      path.resolve(__dirname, '../src/assets/env.js'),
      fileContent
    );
  2. Include generated file in angular.json assets:

    json
    "assets": [
      { "glob": "env.js", "input": "src/assets", "output": "/assets" }
    ]
  3. Run script before build/serve scripts:

    json
    "scripts": {
      "prebuild": "node build-scripts/env.js",
      "build": "ng build"
    }
  4. Add to .gitignore:

    :.gitignore
    src/assets/env.js
  5. Access variables in components:

    typescript
    declare const window: any;
    
    const apiUrl = window.__env.NG_APP_API_URL;

Tradeoffs

Pros:

  • No rebuild required for environment changes
  • CI/CD pipeline friendly

Cons:

  • Variables exposed in client-side JavaScript
  • Added build complexity
  • Not Angular's standard approach

Migration Note for Angular 14 Projects

Existing projects upgrading to Angular 15 will retain their environments folder. No automatic migration is needed. New projects created with Angular 15+ require explicit environment setup.

Best Practices Summary

  1. For most projects: ng generate environments
  2. For custom configurations: Manual setup with file replacements
  3. For dynamic CI/CD environments: Runtime variable injection
  4. Always store sensitive variables server-side; never in client files

Why Environments Changed

Angular moved away from environment files by default to:

  • Reduce unnecessary files in projects not needing environments
  • Support more flexible configuration methods
  • Align with future configuration improvements

For advanced workflows, see the official Angular Environment Configuration Guide.