search
Angular star Featured

Fix: Angular app not working after build (production issue)

Learn how to fix Angular applications that don't work after production build. This comprehensive guide covers common production issues, optimization, and best practices.

person By Gautam Sharma
calendar_today January 2, 2026
schedule 13 min read
Angular Production Build Error Frontend Development Optimization Deployment

The ‘Angular app not working after build’ is a common production deployment issue that occurs when an Angular application functions correctly in development but fails after building for production. This problem typically stems from differences between development and production build configurations, optimization processes, or environment-specific code.

This comprehensive guide explains what causes this issue, why it happens, and provides multiple solutions to fix it in your Angular projects with clean code examples and directory structure.


What is the Production Build Issue?

The “Angular app not working after build” issue manifests when your application:

  • Builds successfully but fails to load in the browser
  • Shows blank pages or runtime errors in production
  • Works in development but breaks after ng build --prod
  • Has different behavior between development and production environments

Common Error Manifestations:

  • Blank white screen after build
  • JavaScript runtime errors in production
  • Assets not loading after build
  • Routing issues in production
  • Service worker problems
  • Lazy loading failures

Understanding the Problem

Production builds differ from development builds in several ways:

  • Code optimization and minification
  • Tree shaking and dead code elimination
  • Different build configurations
  • Environment-specific code paths
  • Service worker activation
  • Asset path differences

Typical Angular Project Structure:

my-angular-app/
├── package.json
├── angular.json
├── src/
│   ├── app/
│   │   ├── app.component.ts
│   │   ├── app.component.html
│   │   ├── app.module.ts
│   │   ├── app-routing.module.ts
│   │   ├── services/
│   │   │   └── data.service.ts
│   │   ├── components/
│   │   │   └── my-component/
│   │   │       ├── my-component.component.ts
│   │   │       └── my-component.component.html
│   │   └── environments/
│   │       ├── environment.ts
│   │       └── environment.prod.ts
│   ├── assets/
│   ├── index.html
│   └── styles.css
├── dist/
│   └── my-app/
│       ├── index.html
│       ├── main.js
│       ├── polyfills.js
│       └── ...
└── node_modules/

Solution 1: Check Production Build Configuration

Ensure your production build configuration is correct.

❌ Incorrect Production Configuration:

// angular.json - Incorrect production configuration
{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "configurations": {
            "production": {
              "optimization": false, // ❌ Should be true for production
              "buildOptimizer": false, // ❌ Should be true for production
              "outputHashing": "none", // ❌ Should use hashing for cache busting
              "sourceMap": true // ❌ Should be false in production
            }
          }
        }
      }
    }
  }
}

✅ Correct Production Configuration:

angular.json:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "my-app": {
      "projectType": "application",
      "schematics": {},
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/my-app",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": [
              "zone.js"
            ],
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ],
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true, // ✅ Enable optimization
              "outputHashing": "all", // ✅ Enable hashing
              "sourceMap": false, // ✅ Disable source maps
              "namedChunks": false, // ✅ Disable named chunks
              "extractLicenses": true, // ✅ Extract licenses
              "vendorChunk": false, // ✅ Disable vendor chunk
              "buildOptimizer": true, // ✅ Enable build optimizer
              "serviceWorker": true, // ✅ Enable service worker if needed
              "ngswConfigPath": "ngsw-config.json" // ✅ Service worker config
            },
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "sourceMap": true,
              "namedChunks": true
            }
          },
          "defaultConfiguration": "production"
        }
      }
    }
  }
}

Solution 2: Fix Environment-Specific Code

Ensure environment-specific code works in both development and production.

❌ Environment-Specific Issues:

// src/app/services/data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  // ❌ Hardcoded development URL
  private apiUrl = 'http://localhost:3000/api';

  constructor(private http: HttpClient) { }

  getData() {
    return this.http.get(this.apiUrl);
  }
}

✅ Environment-Aware Code:

environment.ts (Development):

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

environment.prod.ts (Production):

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

Updated Service:

// src/app/services/data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private apiUrl = environment.apiUrl; // ✅ Use environment-specific URL

  constructor(private http: HttpClient) { }

  getData() {
    return this.http.get(this.apiUrl);
  }
}

Solution 3: Handle Runtime Errors Properly

Implement proper error handling for production environments.

error-handler.service.ts:

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

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  handleError(error: any): void {
    // Log error in development
    if (!environment.production) {
      console.error('Error:', error);
    }

    // Send error to logging service in production
    if (environment.production) {
      this.logError(error);
    }

    // Re-throw the error
    throw error;
  }

  private logError(error: any): void {
    // Send error to your logging service
    console.error('Production Error:', error);
    // Example: send to external logging service
    // this.loggingService.log(error);
  }
}

app.module.ts:

import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { GlobalErrorHandler } from './services/error-handler.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    { provide: ErrorHandler, useClass: GlobalErrorHandler } // ✅ Global error handler
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Solution 4: Fix Asset Path Issues

Ensure asset paths work correctly in production builds.

❌ Incorrect Asset Paths:

<!-- src/index.html - Incorrect asset paths -->
<head>
  <!-- ❌ Relative paths may break in production -->
  <link rel="stylesheet" href="assets/styles.css">
  <link rel="icon" href="assets/favicon.ico">
</head>

✅ Correct Asset Paths:

index.html:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My App</title>
  <base href="/"> <!-- ✅ Base href for routing -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="manifest" href="manifest.webmanifest">
  <meta name="theme-color" content="#1976d2">
</head>
<body>
  <app-root></app-root>
  <noscript>Please enable JavaScript to continue using this application.</noscript>
</body>
</html>

assets/ subdirectory structure:

src/assets/
├── images/
│   ├── logo.png
│   └── background.jpg
├── data/
│   └── config.json
└── favicon.ico

Solution 5: Configure Base Href for Routing

Set the correct base href for Angular routing in production.

❌ Without Base Href:

<!-- Without base href, routing may fail in production -->
<head>
  <title>My App</title>
  <!-- Missing base href -->
</head>

✅ With Base Href:

Build with Base Href:

# Build with specific base href
ng build --base-href="/my-app/"

# Or set in angular.json
# "baseHref": "/my-app/"

angular.json (Base Href Configuration):

{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "options": {
            "baseHref": "/" // ✅ Set base href for routing
          }
        }
      }
    }
  }
}

Solution 6: Fix Lazy Loading Issues

Ensure lazy-loaded modules work correctly in production builds.

feature-routing.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { FeatureComponent } from './feature.component';

const routes: Routes = [
  {
    path: 'feature',
    component: FeatureComponent,
    data: { preload: true } // ✅ Preload strategy
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class FeatureRoutingModule { }

feature.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FeatureComponent } from './feature.component';
import { FeatureRoutingModule } from './feature-routing.module';

@NgModule({
  declarations: [
    FeatureComponent
  ],
  imports: [
    CommonModule,
    FeatureRoutingModule
  ]
})
export class FeatureModule { }

Solution 7: Implement Proper Service Worker Configuration

Configure service worker for production caching and offline support.

ngsw-config.json:

{
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/manifest.webmanifest",
          "/*.css",
          "/*.js"
        ]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
        ]
      }
    }
  ]
}

Working Code Examples

Complete Production-Ready Component:

// src/app/components/production-ready/production-ready.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { environment } from '../../environments/environment';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-production-ready',
  template: `
    <div class="production-component">
      <h2>Environment: {{ environmentName }}</h2>
      <p>Production Mode: {{ isProduction }}</p>
      <button (click)="loadData()">Load Data</button>
      <div *ngIf="loading">Loading...</div>
      <div *ngIf="error" class="error">{{ error }}</div>
      <div *ngIf="data">{{ data | json }}</div>
    </div>
  `,
  styles: [`
    .production-component { padding: 20px; }
    .error { color: red; }
  `]
})
export class ProductionReadyComponent implements OnInit, OnDestroy {
  environmentName = environment.production ? 'Production' : 'Development';
  isProduction = environment.production;
  data: any = null;
  loading = false;
  error: string | null = null;
  private subscription = new Subscription();

  ngOnInit() {
    // Initialize component for production
    console.log('Component initialized in', this.environmentName, 'mode');
  }

  ngOnDestroy() {
    // Clean up subscriptions in production
    this.subscription.unsubscribe();
  }

  loadData() {
    this.loading = true;
    this.error = null;
    
    // Simulate data loading with proper error handling
    setTimeout(() => {
      try {
        if (Math.random() > 0.1) { // 90% success rate
          this.data = { message: 'Data loaded successfully' };
        } else {
          throw new Error('Failed to load data');
        }
      } catch (error: any) {
        this.error = environment.production 
          ? 'An error occurred. Please try again.' // User-friendly message in production
          : error.message; // Detailed error in development
      } finally {
        this.loading = false;
      }
    }, 1000);
  }
}

Production-Ready Service:

// src/app/services/production-service.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError, of } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { environment } from '../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class ProductionService {
  private apiUrl = environment.apiUrl;

  constructor(private http: HttpClient) { }

  getData(): Observable<any> {
    return this.http.get(this.apiUrl).pipe(
      retry(2), // Retry failed requests
      catchError((error: HttpErrorResponse) => {
        let errorMessage = '';
        
        if (environment.production) {
          // Production error handling
          errorMessage = 'An error occurred. Please try again.';
        } else {
          // Development error handling
          if (error.error instanceof ErrorEvent) {
            errorMessage = `Client Error: ${error.error.message}`;
          } else {
            errorMessage = `Server Error: ${error.status} - ${error.message}`;
          }
        }
        
        console.error('API Error:', errorMessage);
        return throwError(() => new Error(errorMessage));
      })
    );
  }
}

Best Practices for Production Builds

1. Use Production Environment Variables

// ✅ Always use environment variables for configuration
export const API_CONFIG = {
  BASE_URL: environment.apiUrl,
  TIMEOUT: environment.production ? 5000 : 10000
};

2. Implement Proper Logging

// ✅ Use conditional logging based on environment
if (!environment.production) {
  console.log('Debug info:', data);
}

3. Optimize Bundle Size

# ✅ Use build optimization
ng build --optimization=true --build-optimizer=true

4. Test Production Builds Locally

# ✅ Serve production build locally for testing
ng build --configuration=production
npx http-server dist/my-app

Debugging Production Issues

Step 1: Enable Production Error Logging

// Add error logging in production
if (environment.production) {
  window.addEventListener('error', (event) => {
    console.error('Production Error:', event.error);
    // Send to error tracking service
  });
}

Step 2: Check Browser Console

# Open browser developer tools and check console for errors
# Look for JavaScript errors, network failures, or CORS issues

Step 3: Test Production Build Locally

# Build and serve production version locally
ng build --configuration=production
npx http-server dist/my-app

Step 4: Verify Asset Loading

# Check if all assets (CSS, JS, images) are loading correctly
# Look for 404 errors in network tab

Common Production Issues to Avoid

1. Development-Specific Code in Production

// ❌ Don't use development-specific code in production
if (location.hostname === 'localhost') {
  // This won't work in production
}

// ✅ Use environment variables instead
if (!environment.production) {
  // Development-specific code
}

2. Hardcoded URLs

// ❌ Don't hardcode URLs
private apiUrl = 'http://localhost:3000/api';

// ✅ Use environment variables
private apiUrl = environment.apiUrl;

3. Missing Polyfills

// ✅ Ensure all necessary polyfills are included
// Check browser compatibility requirements

4. Incorrect Base Href

<!-- ✅ Always set correct base href -->
<base href="/">

Performance Considerations

1. Optimize Bundle Size

# Analyze bundle size
npm install -g webpack-bundle-analyzer
ng build --stats-json
npx webpack-bundle-analyzer dist/my-app/stats.json

2. Implement Lazy Loading

// ✅ Use lazy loading for feature modules
const routes: Routes = [
  {
    path: 'feature',
    loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
  }
];

3. Use OnPush Change Detection

// ✅ Use OnPush strategy for performance
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent { }

Security Considerations

1. Sanitize User Input

// ✅ Always sanitize user input in production
import { DomSanitizer } from '@angular/platform-browser';

export class MyComponent {
  constructor(private sanitizer: DomSanitizer) {}
  
  sanitizeContent(content: string) {
    return this.sanitizer.bypassSecurityTrustHtml(content);
  }
}

2. Secure API Calls

// ✅ Use HTTPS in production
private apiUrl = environment.production 
  ? 'https://api.myapp.com' 
  : 'http://localhost:3000/api';

Testing Production Builds

1. Build and Serve Test

# Build for production
ng build --configuration=production

# Serve locally to test
npx http-server dist/my-app

2. End-to-End Testing

# Run e2e tests on production build
ng e2e

3. Performance Testing

# Use Lighthouse for performance testing
npx lighthouse http://localhost:8080

Alternative Solutions

1. Use Different Build Configurations

# Create custom build configurations
ng build --configuration=staging

2. Implement Feature Flags

// Use feature flags for production
export const FEATURES = {
  NEW_UI: environment.production ? false : true,
  BETA_FEATURES: false
};

Migration Checklist

  • Verify production build configuration in angular.json
  • Check environment-specific code and variables
  • Test production build locally before deployment
  • Verify asset paths and base href configuration
  • Implement proper error handling for production
  • Test lazy loading modules in production build
  • Verify service worker configuration (if used)
  • Check bundle size and optimize if necessary
  • Update documentation for team members

Conclusion

The ‘Angular app not working after build’ issue is typically caused by differences between development and production build configurations, environment-specific code, or optimization-related problems. By following the solutions provided in this guide—whether through proper build configuration, environment management, error handling, or asset path fixes—you can ensure your Angular applications work seamlessly in production environments.

The key is to understand the differences between development and production builds, implement proper environment management, and thoroughly test production builds before deployment. With proper configuration and testing, your Angular applications will function correctly in both development and production environments, providing a reliable user experience.

Remember to always test production builds locally, implement proper error handling, and follow Angular’s best practices for production deployments to ensure your applications are robust and performant in real-world scenarios.

Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

Angular

Fix: Angular Production Mode Errors - Debug Production-Only Issues

Complete guide to fix Angular errors that occur only in production mode. Learn how to debug and resolve production-specific issues with practical solutions, optimization strategies, and best practices for Angular deployment.

January 8, 2026
Angular

Fix: Angular ExpressionChangedAfterItHasBeenCheckedError Error

Learn how to fix the 'ExpressionChangedAfterItHasBeenCheckedError' in Angular. This comprehensive guide covers change detection, lifecycle hooks, and best practices.

January 2, 2026
Angular

How to Fix Cannot find module '@angular/compiler-cli Error in Angular'

Learn how to fix the 'Cannot find module @angular/compiler-cli' error in Angular projects. This comprehensive guide covers installation, dependencies, and best practices.

January 2, 2026