Chapter 5.5โ˜• 14 min read

Environment Config & Multi-provider Tokens

Manage environment-specific settings and provide multiple services for the same token.

01Why Environment Configuration

Every app has different settings for different environments โ€” development, staging, production. You need different API URLs, feature flags, and debugging tools for each.

// Development: http://localhost:4200/api
// Staging: https://staging-api.hyderabad.com
// Production: https://api.hyderabad.com

Environment configuration keeps these differences organized and prevents accidentally using production API keys in development.

02Old Way โ€” environment.ts Files

The traditional approach uses separate files for each environment with angular.json handling the swap during build.

// src/environments/environment.ts (dev)
export const environment = {
  production: false,
  apiUrl: 'http://localhost:4200/api',
  enableDebug: true
};

// src/environments/environment.prod.ts (prod)
export const environment = {
  production: true,
  apiUrl: 'https://api.hyderabad.com',
  enableDebug: false
};

Problem: Easy to accidentally import the wrong file. Not tree-shakeable โ€” unused config stays in bundle.

03New Way โ€” app.config.ts with provideAppConfig

Modern Angular (17+) uses app.config.ts with InjectionToken-based configuration. No file swapping needed.

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { API_URL, APP_CONFIG, IS_PRODUCTION } from './config/app-config';

function getApiUrl(): string {
  return window.location.hostname === 'localhost'
    ? 'http://localhost:4200/api'
    : 'https://api.hyderabad.com';
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
    { provide: API_URL, useFactory: getApiUrl },
    { provide: IS_PRODUCTION, useValue: !getApiUrl().includes('localhost') },
  ]
};

Benefits: Single file, type-safe, tree-shakeable, no file replacement config needed. The factory function determines the value at runtime based on the hostname.

04Multi-Provider Tokens

Some Angular features need MULTIPLE providers for the same token. For example, HTTP_INTERCEPTORS โ€” you can have multiple interceptors, and Angular runs them in order.

// New way โ€” functional interceptors
provideHttpClient(
  withInterceptors([authInterceptor, loggingInterceptor, errorInterceptor])
);

// Old way โ€” class-based with multi: true
providers: [
  { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
  { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },
]

What multi: true does: Instead of one provider replacing the previous one, Angular collects ALL providers with multi: true into an array. inject(HTTP_INTERCEPTORS) returns [AuthInterceptor, LoggingInterceptor, ErrorInterceptor].

Common multi tokens: HTTP_INTERCEPTORS, APP_INITIALIZER, LOCALE_ID.

05Best Practices for Config

Follow these practices for clean, maintainable configuration:

1. Use InjectionToken for config, not environment objects

// GOOD
const API_URL = new InjectionToken('api-url');

// AVOID โ€” old pattern
import { environment } from './environments/environment';

2. Group related providers โ€” keep app.config.ts clean by grouping config providers into a single function.

3. Secrets NEVER in frontend config โ€” API keys and passwords in environment.ts are visible in the browser. Use a backend proxy.

4. Feature flags as InjectionToken โ€” type-safe feature flags with InjectionToken<Record<string, boolean>>.

5. Keep config files focused โ€” one config file per domain (api, auth, features).

Key Takeaways

  • โœ… Environment config manages different settings for dev/staging/production
  • โœ… Old way: environment.ts files with angular.json fileReplacements
  • โœ… New way: InjectionToken + useFactory in app.config.ts โ€” no file swapping
  • โœ… multi: true collects multiple providers for the same token into an array
  • โœ… Never put secrets in frontend config โ€” always use a backend proxy
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase