Skip to main content

Angular PWA Introduction

What is a Progressive Web Application (PWA)?

Progressive Web Applications (PWAs) represent a modern approach to web development that combines the best of web and mobile applications. PWAs are web applications that use modern web capabilities to provide users with an experience similar to native applications.

At their core, PWAs are:

  • Reliable: They load instantly and never show the "downasaur" (offline dinosaur) when there's no network connection
  • Fast: They respond quickly to user interactions with smooth animations and jank-free scrolling
  • Engaging: They feel like a natural app on the device, with an immersive user experience

Why Build PWAs with Angular?

Angular provides excellent support for developing PWAs through the @angular/pwa package. Here are some benefits of building PWAs with Angular:

  1. Built-in PWA Support: Angular CLI makes adding PWA features straightforward with a simple command
  2. Service Worker Integration: Simplified management of service workers for offline capabilities
  3. App Shell Architecture: Angular facilitates implementing the app shell pattern for instant loading
  4. Tooling: Comprehensive tools for building, testing, and deploying PWAs

Key PWA Features in Angular

Service Workers

Service workers act as proxy servers that sit between web applications, the browser, and the network. They enable:

  • Offline capabilities
  • Background sync
  • Push notifications
  • Content caching

Web App Manifest

A JSON file that provides information about a web application, including:

  • App name and description
  • Icons for different screen sizes
  • Theme colors
  • Display mode (standalone, fullscreen, etc.)

App Shell Architecture

An application shell is the minimal HTML, CSS, and JavaScript required to power the user interface. It:

  • Loads quickly on repeat visits
  • Provides instant, reliable performance
  • Displays content while awaiting data

Setting Up Your First Angular PWA

Let's walk through creating a basic Angular PWA:

Step 1: Create a new Angular project

bash
ng new my-pwa-app
cd my-pwa-app

Step 2: Add PWA capabilities using Angular CLI

bash
ng add @angular/pwa

This command performs several important changes to your application:

  1. Adds the @angular/service-worker package
  2. Enables service worker support in the Angular CLI
  3. Imports and registers the service worker in the app module
  4. Updates the index.html file with a link to the manifest file and theme color
  5. Creates icons for the PWA
  6. Creates the configuration file for the service worker (ngsw-config.json)

Let's examine what the updated app.module.ts looks like:

typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ServiceWorkerModule } from '@angular/service-worker';
import { AppComponent } from './app.component';
import { environment } from '../environments/environment';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
// Register the ServiceWorker as soon as the application is stable
// or after 30 seconds (whichever comes first)
registrationStrategy: 'registerWhenStable:30000'
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Step 3: Inspect the ngsw-config.json file

This file configures the service worker and controls how it caches resources:

json
{
"$schema": "./node_modules/@angular/service-worker/config/schema.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)"
]
}
}
]
}

Step 4: Inspect the web manifest file

The manifest.webmanifest file contains metadata about your application:

json
{
"name": "my-pwa-app",
"short_name": "my-pwa-app",
"theme_color": "#1976d2",
"background_color": "#fafafa",
"display": "standalone",
"scope": "./",
"start_url": "./",
"icons": [
{
"src": "assets/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
},
// More icon definitions...
{
"src": "assets/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable any"
}
]
}

Step 5: Build and test your PWA

To test your PWA, you need to build it in production mode and serve it:

bash
ng build --configuration production

After building, you can use a simple HTTP server to serve your PWA:

bash
npx http-server -p 8080 -c-1 dist/my-pwa-app

Open your browser and navigate to http://localhost:8080. You can inspect the service worker in the browser's developer tools under the "Application" tab.

Real-World Example: Creating an Offline-Capable News App

Let's consider a practical example of how PWAs can improve user experience.

Scenario: News Application

Imagine we're building a news application where users should be able to:

  • Read news articles even when offline
  • Receive push notifications for breaking news
  • Install the app on their home screen

Implementing Offline News Reading

First, we'll configure our service worker to cache news articles:

typescript
// In ngsw-config.json, add a dataGroups section:
{
// ... existing configuration
"dataGroups": [
{
"name": "news-api",
"urls": [
"https://api.example.com/news"
],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "1h",
"timeout": "10s"
}
}
]
}

Then, in our news service:

typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';

@Injectable({
providedIn: 'root'
})
export class NewsService {
private readonly NEWS_API_URL = 'https://api.example.com/news';
private cachedNews: any[] = [];

constructor(private http: HttpClient) {}

getNews(): Observable<any[]> {
return this.http.get<any[]>(this.NEWS_API_URL).pipe(
tap(news => this.cachedNews = news),
catchError(() => {
console.log('Returning cached news due to network error');
return of(this.cachedNews);
})
);
}
}

Adding Push Notifications

To enable push notifications in our Angular application:

typescript
// In app.component.ts
import { SwPush } from '@angular/service-worker';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
readonly VAPID_PUBLIC_KEY = 'your-public-key-here';

constructor(private swPush: SwPush) {}

subscribeToNotifications() {
this.swPush.requestSubscription({
serverPublicKey: this.VAPID_PUBLIC_KEY
})
.then(sub => {
// Send subscription to server
console.log('Successfully subscribed to notifications', sub);
})
.catch(err => console.error('Could not subscribe to notifications', err));
}
}
html
<!-- In app.component.html -->
<button (click)="subscribeToNotifications()">
Subscribe to Breaking News Alerts
</button>

Testing PWA Features

To thoroughly test your Angular PWA:

  1. Offline Testing: Enable "Offline" mode in Chrome DevTools' Network tab to verify your app works without a connection

  2. Lighthouse Audit: Run a Lighthouse audit in Chrome DevTools to get a PWA score and recommendations for improvement

  3. Installation Testing: Confirm your app shows the "Add to Home Screen" prompt and installs correctly

  4. Push Notifications: Test if notifications appear correctly when triggered

Summary

In this introduction to Angular PWAs, we've learned:

  • What Progressive Web Applications are and their core features
  • How Angular supports PWA development through built-in tools
  • The key components of a PWA: service workers, web app manifest, and app shell
  • How to set up a basic Angular PWA project
  • A real-world example of implementing offline capabilities and push notifications

PWAs represent the future of web development, combining the reach of web applications with the capabilities of native apps. With Angular's robust tooling and your new understanding of PWA concepts, you're well-positioned to build modern, responsive applications that work seamlessly across devices and network conditions.

Additional Resources

Exercises

  1. Create a simple Angular PWA that displays a list of items and allows users to view them offline.
  2. Modify the ngsw-config.json file to cache API responses from an external service.
  3. Implement a "new content available" notification when your PWA has an update.
  4. Add custom install prompts to improve the user experience when adding your PWA to the home screen.
  5. Build a PWA that syncs user data when coming back online after being offline.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)