Angular’s environment system provides build-time configuration — different values for development, staging, and production builds. The API URL, feature flags, analytics IDs, and debug settings all live in environment files. The correct approach in Angular 18 is to inject environment values via a typed InjectionToken rather than importing the environment file directly in services — this makes services testable (no file system dependency) and follows the dependency injection pattern consistently.
Angular Environment Configuration
// ── src/environments/environment.ts — development ─────────────────────────
export const environment = {
production: false,
apiUrl: 'http://localhost:5000', // ASP.NET Core API
enableDebugTools: true,
appVersion: '1.0.0-dev',
features: {
comments: true,
darkMode: true,
analytics: false,
}
};
// ── src/environments/environment.prod.ts — production ─────────────────────
export const environment = {
production: true,
apiUrl: 'https://api.blogapp.com', // production API
enableDebugTools: false,
appVersion: '1.0.0',
features: {
comments: true,
darkMode: true,
analytics: true,
}
};
// ── angular.json — build configurations ──────────────────────────────────
// "configurations": {
// "production": {
// "fileReplacements": [{
// "replace": "src/environments/environment.ts",
// "with": "src/environments/environment.prod.ts"
// }],
// "optimization": true,
// "sourceMap": false,
// "aot": true
// },
// "staging": {
// "fileReplacements": [{
// "replace": "src/environments/environment.ts",
// "with": "src/environments/environment.staging.ts"
// }]
// }
// }
// ── Typed injection token — preferred over direct import ──────────────────
// src/app/core/tokens/app-config.token.ts
import { InjectionToken } from '@angular/core';
export interface AppConfig {
apiUrl: string;
production: boolean;
enableDebugTools: boolean;
appVersion: string;
}
export const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');
// ── app.config.ts — provide the token ────────────────────────────────────
import { environment } from '../environments/environment';
import { APP_CONFIG } from './core/tokens/app-config.token';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withInterceptors([authInterceptor, errorInterceptor])),
{ provide: APP_CONFIG, useValue: environment }, // inject env as typed config
],
};
// ── Service using the token (testable — no direct env import) ─────────────
@Injectable({ providedIn: 'root' })
export class PostsApiService {
private config = inject(APP_CONFIG);
private http = inject(HttpClient);
private apiUrl = `${this.config.apiUrl}/api/posts`;
getPublished(page = 1, size = 10): Observable<PagedResult<PostSummaryDto>> {
return this.http.get<PagedResult<PostSummaryDto>>(this.apiUrl, {
params: { page, size },
});
}
}
InjectionToken approach makes services unit-testable without file system dependencies. In tests, provide the token with test values: { provide: APP_CONFIG, useValue: { apiUrl: 'http://test-api', production: false } }. If services imported the environment file directly, tests would use the development environment values, which may differ from the test environment or require mocking file imports. The injection token approach follows Angular’s DI principles and produces cleaner, more portable services.appVersion to the environment and display it in the footer or a debug overlay. When users report bugs, knowing the exact app version helps diagnose whether the issue was already fixed in a newer deployment. Also useful in Angular error interceptors — include the app version in error reports sent to a monitoring service (Sentry, Application Insights) for correlation with deployment timelines.Common Mistakes
Mistake 1 — Importing environment directly in services (not testable)
❌ Wrong — import { environment } from '../../environments/environment' in a service; hard to test without file mocking.
✅ Correct — inject APP_CONFIG token; provide test values in unit test providers.
Mistake 2 — API secrets in environment files (exposed in browser bundle)
❌ Wrong — server-side API key in environment.prod.ts; compiled into JS bundle; visible in browser DevTools.
✅ Correct — server-side secrets in server environment variables only; Angular environment files are public.