Saturday, August 16, 2025
0 comments

Master Angular 20 Build & Deployment: A Beginner’s Guide to Environment Files, Production Builds, and Deploying to Local Servers, GitHub Pages, and Firebase Hosting

 




Angular Environment Files (environment.ts)Angular uses environment files to manage configuration settings for different environments (e.g., development, production). These files allow you to define variables like API URLs or feature flags that change based on the environment.Key Concepts
  • Default Files:
    • src/environments/environment.ts: Used for development.
    • src/environments/environment.prod.ts: Used for production builds.
  • Usage: Import environment variables in services or components.
  • Build Configuration: Angular CLI swaps environment.ts with environment.prod.ts during production builds (ng build --prod).
  • Custom Environments: Add additional environments (e.g., staging) in angular.json.
Example: Environment Files
typescript
// src/environments/environment.ts (Development)
export const environment = {
  production: false,
  apiUrl: 'https://freeapi.miniprojectideas.com/api/User'
};
typescript
// src/environments/environment.prod.ts (Production)
export const environment = {
  production: true,
  apiUrl: 'https://freeapi.miniprojectideas.com/api/User'
};
Using Environment Variables:
typescript
// src/app/services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { environment } from '../../environments/environment';
import { User } from '../models/user.model';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = environment.apiUrl; // Use environment variable
  // ...
}
Explanation:
  • environment.apiUrl provides the API endpoint.
  • production: false in development enables debugging; production: true optimizes the build.
  • The CLI automatically uses environment.prod.ts for production builds.
Adding a Custom Environment (e.g., Staging)
  1. Create environment.staging.ts:
    typescript
    // src/environments/environment.staging.ts
    export const environment = {
      production: false,
      apiUrl: 'https://staging.freeapi.miniprojectideas.com/api/User'
    };
  2. Update 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"
          }
        ],
        "optimization": true,
        "outputHashing": "all",
        "sourceMap": false,
        "namedChunks": false,
        "extractLicenses": true,
        "vendorChunk": true,
        "buildOptimizer": true
      }
    }
  3. Build for staging:
    bash
    ng build --configuration=staging

Building the App (ng build --prod)The ng build command compiles your Angular app into static files (HTML, CSS, JavaScript) for deployment. The --prod flag optimizes the build for production.Key Features of ng build --prod
  • Tree Shaking: Removes unused code.
  • Minification: Reduces file sizes by compressing code.
  • Ahead-of-Time (AOT) Compilation: Compiles templates at build time for faster rendering.
  • Output: Generates files in the dist/ folder.
Steps to Build
  1. Run the build command:
    bash
    ng build --prod
  2. Check the output in dist/angular-routing-demo/.
Output Structure:
dist/angular-routing-demo/
├── index.html
├── main.[hash].js
├── polyfills.[hash].js
├── runtime.[hash].js
├── styles.[hash].css
├── assets/
└── favicon.ico
Explanation:
  • index.html: Entry point for the app.
  • main.[hash].js: Application code with a hash for cache busting.
  • styles.[hash].css: Compiled SCSS/CSS.
  • assets/: Static files (e.g., images).
Configuring angular.jsonEnsure the baseHref and deployUrl are set correctly for deployment:
json
"projects": {
  "angular-routing-demo": {
    "architect": {
      "build": {
        "options": {
          "outputPath": "dist/angular-routing-demo",
          "index": "src/index.html",
          "main": "src/main.ts",
          "baseHref": "/",
          "deployUrl": "/"
        }
      }
    }
  }
}

Deploying to a Local ServerA local server is useful for testing the production build locally before deploying to a hosting service.Using http-server
  1. Install http-server globally:
    bash
    npm install -g http-server
  2. Build the app:
    bash
    ng build --prod
  3. Serve the build:
    bash
    cd dist/angular-routing-demo
    http-server -p 8080
  4. Visit http://localhost:8080 in your browser.
Explanation:
  • http-server serves static files from dist/.
  • Verify routing, API calls, and authentication work as expected.

Deploying to GitHub PagesGitHub Pages hosts static websites directly from a GitHub repository, ideal for Angular apps.Steps to Deploy
  1. Install the angular-cli-ghpages package:
    bash
    npm install -g angular-cli-ghpages
  2. Update baseHref for your GitHub Pages URL (e.g., https://<username>.github.io/angular-routing-demo/):
    json
    // angular.json
    "baseHref": "/angular-routing-demo/"
  3. Build the app:
    bash
    ng build --prod --base-href /angular-routing-demo/
  4. Deploy to GitHub Pages:
    bash
    ngh --dir=dist/angular-routing-demo
  5. Create a GitHub repository (angular-routing-demo) and push the code:
    bash
    git init
    git add .
    git commit -m "Initial commit"
    git remote add origin https://github.com/<username>/angular-routing-demo.git
    git push -u origin main
  6. Enable GitHub Pages in the repository settings:
    • Go to Settings > Pages.
    • Select the main branch and / (root) folder.
  7. Visit https://<username>.github.io/angular-routing-demo/.
Notes:
  • Ensure baseHref matches the repository name.
  • Test the deployed app to confirm routing and API calls work.

Deploying to Firebase HostingFirebase Hosting provides a scalable, secure platform for hosting Angular apps with easy deployment.Steps to Deploy
  1. Install the Firebase CLI:
    bash
    npm install -g firebase-tools
  2. Log in to Firebase:
    bash
    firebase login
  3. Initialize Firebase Hosting:
    bash
    firebase init hosting
    • Select “Use an existing project” or create a new one.
    • Set dist/angular-routing-demo as the public directory.
    • Configure as a single-page app (SPA) by answering “Yes” to “Configure as a single-page app (rewrite all urls to /index.html)?”.
    • Example firebase.json:
      json
      {
        "hosting": {
          "public": "dist/angular-routing-demo",
          "ignore": [
            "firebase.json",
            "**/.*",
            "**/node_modules/**"
          ],
          "rewrites": [
            {
              "source": "**",
              "destination": "/index.html"
            }
          ]
        }
      }
  4. Build the app:
    bash
    ng build --prod
  5. Deploy to Firebase:
    bash
    firebase deploy
  6. Visit the provided URL (e.g., https://<project-id>.web.app).
Notes:
  • Firebase Hosting automatically handles SPA routing.
  • Ensure CORS is enabled for freeapi.miniprojectideas.com if needed.

Hands-On Project: Build and Deploy angular-routing-demoLet’s build and deploy the angular-routing-demo project to a local server, GitHub Pages, and Firebase Hosting, ensuring:
  1. Environment files manage API URLs.
  2. The production build is optimized.
  3. The /admin route remains protected with AuthGuard.
  4. Integration with freeapi.miniprojectideas.com, StateService, AuthService, and Angular Material works seamlessly.
Step 1: Set Up the ProjectEnsure the project is set up (from Module 11):
bash
ng new angular-routing-demo --style=scss
cd angular-routing-demo
ng add @angular/material
ng g component components/user
ng g component components/admin
ng g component components/user-details
ng g component components/not-found
ng g component components/admin-dashboard
ng g component components/admin-settings
ng g component components/register
ng g component components/login
ng g component components/user-info
ng g component components/header
ng g component components/footer
ng g pipe pipes/filter-by-role
ng g service services/user
ng g service services/storage
ng g service services/state
ng g service services/auth
ng g guard guards/auth
ng g guard guards/can-deactivate
  • Select the Indigo/Pink theme during ng add @angular/material.
  • Choose CanActivate for AuthGuard and CanDeactivate for CanDeactivateGuard.
Step 2: Set Up Environment Files
typescript
// src/environments/environment.ts
export const environment = {
  production: false,
  apiUrl: 'https://freeapi.miniprojectideas.com/api/User'
};
typescript
// src/environments/environment.prod.ts
export const environment = {
  production: true,
  apiUrl: 'https://freeapi.miniprojectideas.com/api/User'
};
Step 3: Update UserService to Use Environment
typescript
// src/app/services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, finalize } from 'rxjs/operators';
import { User } from '../models/user.model';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = `${environment.apiUrl}/GetAllUsers`;
  private localUsers: User[] = [
    { id: 1, userName: 'Alice', emailId: 'alice@example.com', role: 'admin' },
    { id: 2, userName: 'Bob', emailId: 'bob@example.com', role: 'user' },
    { id: 3, userName: 'Charlie', emailId: 'charlie@example.com', role: 'admin' },
    { id: 4, userName: 'David', emailId: 'david@example.com', role: 'user' }
  ];
  private admins = [
    { username: 'admin1', password: 'admin123' },
    { username: 'admin2', password: 'admin456' }
  ];

  constructor(private http: HttpClient) {}

  getUsers(): Observable<User[]> {
    return this.http.get<User[]>(this.apiUrl).pipe(
      catchError(error => {
        console.error('Error fetching users from API:', error);
        return of(this.localUsers);
      })
    );
  }

  getUserById(id: number): Observable<User | undefined> {
    return this.http.get<User>(`${this.apiUrl}/${id}`).pipe(
      catchError(error => {
        console.error('Error fetching user by ID:', error);
        const localUser = this.localUsers.find(user => user.id === id);
        return of(localUser);
      })
    );
  }

  addUser(user: User): Observable<any> {
    return this.http.post(this.apiUrl, user).pipe(
      catchError(error => {
        console.error('Error adding user:', error);
        this.localUsers.push(user);
        return of(user);
      })
    );
  }

  validateAdmin(username: string, password: string): boolean {
    return this.admins.some(admin => admin.username === username && admin.password === password);
  }
}
Step 4: Update Other Project FilesUse the code from Module 11 for the following files to maintain consistency:
  • src/app/models/user.model.ts
  • src/app/services/auth.service.ts
  • src/app/services/state.service.ts
  • src/app/services/storage.service.ts
  • src/app/guards/auth.guard.ts
  • src/app/guards/can-deactivate.guard.ts
  • src/app/app.routes.ts
  • src/main.ts
  • src/app/app.component.ts, .html, .scss
  • src/app/components/header/header.component.ts, .html, .scss
  • src/app/components/footer/footer.component.ts, .html, .scss
  • src/app/components/admin/admin.component.ts, .html, .scss
  • src/app/components/user/user.component.ts, .html, .scss
  • src/app/components/user-info/user-info.component.ts, .html, .scss
  • src/app/components/user-details/user-details.component.ts, .html, .scss
  • src/app/components/register/register.component.ts, .html, .scss
  • src/app/components/login/login.component.ts, .html, .scss
  • src/app/components/admin-dashboard/admin-dashboard.component.ts, .html, .scss
  • src/app/components/admin-settings/admin-settings.component.ts, .html, .scss
  • src/app/components/not-found/not-found.component.ts, .html, .scss
  • src/app/pipes/filter-by-role.pipe.ts
  • src/app/validators/no-spaces.validator.ts
  • src/styles.scss
Step 5: Build the App
  1. Run the production build:
    bash
    ng build --prod
  2. Verify the dist/angular-routing-demo/ folder contains the compiled files.
Step 6: Deploy to Local Server
  1. Install http-server:
    bash
    npm install -g http-server
  2. Serve the build:
    bash
    cd dist/angular-routing-demo
    http-server -p 8080
  3. Visit http://localhost:8080 and test:
    • Log in with admin1/admin123 to access /admin.
    • Verify API calls to freeapi.miniprojectideas.com.
    • Check routing and authentication.
Step 7: Deploy to GitHub Pages
  1. Install angular-cli-ghpages:
    bash
    npm install -g angular-cli-ghpages
  2. Update angular.json:
    json
    "baseHref": "/angular-routing-demo/"
  3. Build with the correct base href:
    bash
    ng build --prod --base-href /angular-routing-demo/
  4. Create a GitHub repository (angular-routing-demo):
    bash
    git init
    git add .
    git commit -m "Initial commit"
    git remote add origin https://github.com/<username>/angular-routing-demo.git
    git push -u origin main
  5. Deploy:
    bash
    ngh --dir=dist/angular-routing-demo
  6. Enable GitHub Pages in the repository settings (branch: main, folder: / (root)).
  7. Visit https://<username>.github.io/angular-routing-demo/ and test.
Step 8: Deploy to Firebase Hosting
  1. Install Firebase CLI:
    bash
    npm install -g firebase-tools
  2. Log in to Firebase:
    bash
    firebase login
  3. Initialize Firebase Hosting:
    bash
    firebase init hosting
    • Select your Firebase project.
    • Set dist/angular-routing-demo as the public directory.
    • Configure as an SPA (rewrite all URLs to /index.html).
  4. Build the app:
    bash
    ng build --prod
  5. Deploy:
    bash
    firebase deploy
  6. Visit the provided URL (e.g., https://<project-id>.web.app) and test.
Step 9: Test the Deployed AppFor each deployment (local server, GitHub Pages, Firebase Hosting):
  • Login (/login): Log in with admin1/admin123 and verify redirection to /admin.
  • Admin Route (/admin): Confirm unauthenticated users are redirected to /login.
  • Logout (Header): Log out and verify redirection to /user.
  • Register (/register): Test the CanDeactivate guard by navigating away with unsaved changes.
  • User Dashboard (/user): Verify user list and state management.
  • User Details (/user/:id): Confirm user details display.
  • API Calls: Ensure freeapi.miniprojectideas.com data loads.
  • 404 Page (/invalid): Check the Not Found page.

Troubleshooting Common ErrorsTS2305: Module '"./app/app"' has no exported member 'App'Cause: Incorrect import in main.ts.Fix:
typescript
// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter, provideHttpClient } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
import { provideAnimations } from '@angular/platform-browser/animations';

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
    provideAnimations()
  ]
}).catch(err => console.error(err));
Steps:
  1. Ensure AppComponent is exported in app.component.ts.
  2. Verify file paths.
  3. Run ng serve.
Routing Issues on GitHub Pages or FirebaseCause: Incorrect baseHref or missing SPA configuration.Fix:
  • For GitHub Pages, ensure baseHref matches the repository name:
    bash
    ng build --prod --base-href /angular-routing-demo/
  • For Firebase, verify firebase.json includes the SPA rewrite:
    json
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
API CORS ErrorsCause: freeapi.miniprojectideas.com may block requests from deployed domains.Fix:
  • Use a proxy during development (update angular.json or use a local proxy).
  • For production, ensure the API supports CORS for your deployed domain.
  • Alternatively, use a fallback local dataset in UserService.
Firebase Deployment FailsCause: Incorrect Firebase project or authentication.Fix:
  • Verify firebase login credentials.
  • Ensure the correct project is selected (firebase use <project-id>).
  • Check firebase.json for the correct public directory.

Best Practices for Build & Deployment
  • Use Environment Files: Separate development and production configurations.
  • Optimize Builds: Always use --prod for production to enable AOT and minification.
  • Test Locally: Use http-server to verify the production build before deployment.
  • Set Base Href: Ensure baseHref matches the deployment path.
  • Enable SPA Routing: Configure rewrites for GitHub Pages and Firebase to handle Angular routing.
  • Monitor Performance: Use tools like Lighthouse to test the deployed app’s performance.
  • Secure APIs: Ensure APIs support CORS or use a backend proxy for production.

0 comments:

Featured Post

Master Angular 20 Basics: A Complete Beginner’s Guide with Examples and Best Practices

Welcome to the complete Angular 20 learning roadmap ! This series takes you step by step from basics to intermediate concepts , with hands...

Subscribe

 
Toggle Footer
Top