Mastering Angular Environments

Mastering Angular Environments and Path Aliases with Signals: A Calculator Example

In modern Angular development, using environments, path aliases, and Signals properly can elevate your architecture to enterprise-grade clarity and flexibility.

In this article, we’ll walk through:

  • ✅ Using Angular’s environment configuration with fileReplacements
  • ✅ Configuring path aliases like @environments
  • ✅ Creating a Signal-based service
  • ✅ Building a working calculator component
  • ✅ Professional Angular 19 standards in practice

Step 1: Environment File Setup

We define multiple environment files under src/environments/:

src/
  app/calculator
    calculator.component.ts   
  environments/
    environment.ts
    environment.development.ts
    environment.production.ts

environment.ts (default reference)

export const environment = {
  production: false,
  apiUrl: 'http://localhost:4200'
};

environment.production.ts

export const environment = {
  production: true,
  apiUrl: 'https://api.myapp.com'
};

Step 2: Configure File Replacements

In angular.json, add:

"fileReplacements": [
  {
    "replace": "src/environments/environment.ts",
    "with": "src/environments/environment.development.ts"
  }
]

Step 3: Create a Path Alias @environments

Update your tsconfig.json:

"baseUrl": ".",
"paths": {
  "@environments/*": ["src/environments/*"]
}

Now you can import your environment file like a pro:

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

Step 4: Create the Signal-Powered Calculator Service

import { Injectable, signal } from '@angular/core';
import { environment } from '@environments/environment';

@Injectable({ providedIn: 'root' })
export class CalculatorService {
  private result = signal(0);

  get value() {
    return this.result;
  }

  add(x: number, y: number) {
    const sum = x + y;
    this.log(`Adding: ${x} + ${y} = ${sum}`);
    this.result.set(sum);
  }

  subtract(x: number, y: number) {
    const diff = x - y;
    this.log(`Subtracting: ${x} - ${y} = ${diff}`);
    this.result.set(diff);
  }

  private log(message: string) {
    if (!environment.production) {
      console.log(`[DEV LOG] ${message}`);
    }
  }
}

Step 5: Create a Standalone Calculator Component

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CalculatorService } from '../calculator.service';

@Component({
  imports: [FormsModule],
  standalone: true,
  template: `Calculator
    
    

  Add
  Substract

  Result: {{ calculator.value() }}

  `

})
export class CalculatorComponent {
  x = 0;
  y = 0;

substract() {
  this.calculator.subtract(this.x, this.y);
}
add() {
  this.calculator.add(this.x, this.y);
}
constructor(public calculator: CalculatorService){}

}

Summary

Feature Purpose
environment.ts Control behavior per environment
Path aliases Clean imports like @environments
signal() Reactive state without subscriptions
fileReplacements Seamless dev/prod switching

Final Thoughts

When combined, Signals + Environments + Path Aliases make Angular feel like an elegant framework again. This pattern isn’t just scalable — it’s a pleasure to maintain.

Happy building, and may your configs always compile the right file! ⚡