Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Christian Liebel
@christianliebel
Consultant
Slide 2
Slide 2 text
Hello, it’s me.
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Christian Liebel
X:
@christianliebel
Email:
christian.liebel
@thinktecture.com
Angular & PWA
Slides:
thinktecture.com
/christian-liebel
Slide 3
Slide 3 text
13:30–15:00 Block 1
15:00–15:30 Coffee Break
15:30–17:00 Block 2
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Timetable
Slide 4
Slide 4 text
Things NOT to expect
− Blueprint for PWA development
− No AuthN/AuthZ
Things To Expect
− Extensive/up-to-date insights into
PWA and Project Fugu
− A productivity app use case that
works on your desktop &
smartphone
− Lots of fun
− Hands-on exercises
für Desktop und Mobile mit Angular (Hands-on)
Progressive Web Apps
Slide 5
Slide 5 text
https://paint.js.org
– Productivity app
– Draw images
– Lots of actions & tools
– Installable
– Read/save files
– Copy/paste images from/to
clipboard
– Share files to other apps
– Register for file extensions
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Demo Use Case
Slide 6
Slide 6 text
(Workshop Edition)
– Productivity app
– Draw images
– Lots of actions & tools
– Installable
– Read/save files
– Copy/paste images from/to
clipboard
– Share files to other apps
– Register for file extensions
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Demo Use Case
Slide 7
Slide 7 text
Setup complete?
(Node.js, Google Chrome, Editor, Git)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Setup (1/2)
LAB #0
Slide 8
Slide 8 text
git clone https://github.com/thinktecture/angular-
days-2024-fall-pwa.git
cd angular-days-2024-fall-pwa
npm i
npm start -- --open
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Setup (2/2)
LAB #0
Slide 9
Slide 9 text
Progressive Web Apps
Slide 10
Slide 10 text
Paint PWA Capabilities
Progressive
Enhancement
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Agenda
Slide 11
Slide 11 text
Paint PWA Capabilities
Progressive
Enhancement
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Agenda
Slide 12
Slide 12 text
Canvas
– Plain bitmap for the web
– Cross-platform, hardware-
accelerated graphics operations
– Supports different contexts (2D,
3D: WebGL, WebGL 2.0)
– Supported on all evergreen
browsers and on IE 9+
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
Slide 13
Slide 13 text
Canvas
Add a canvas element to app.component.html:
Query the canvas element in app.component.ts:
canvas = viewChild
.required>('canvas');
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
LAB #1
Slide 14
Slide 14 text
Canvas 2D Context
fillRect(x, y, width, height)
strokeRect(x, y, width, height)
beginPath()
moveTo(x, y)
lineTo(x, y)
fill()
stroke()
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
Slide 15
Slide 15 text
Canvas 2D Context
1. Introduce a new field at the top of
app.component.ts:
context!: CanvasRenderingContext2D;
2. Get the 2D context in ngAfterViewInit():
const canvas =
this.canvas().nativeElement;
const ctx = canvas.getContext('2d')!;
this.context = ctx;
3. Prepare the canvas:
ctx.fillStyle = 'white';
ctx.fillRect(0, 0,
canvas.width,
canvas.height);
ctx.fillStyle = 'black';
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint LAB #2
Slide 16
Slide 16 text
Low-latency Rendering
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
Web pages need to synchronize with the
DOM on graphics updates causing latencies
that can make drawing difficult
Low-latency rendering skips syncing with
the DOM with can lead to a more natural
experience
Supported on Chrome (Chrome OS and
Windows only)
Slide 17
Slide 17 text
Low-latency Rendering
Opt-in to low-latency rendering (app.component.ts):
const ctx = canvas.getContext('2d', {
desynchronized: true
})!;
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
LAB #3
Slide 18
Slide 18 text
Pointer Events
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
Users nowadays use different input
methods, cross-platform apps should
cover all of them
Pointer Events offer an abstract
interface to catch all input methods
(pointerdown, pointermove,
pointerup)
event.offsetX/event.offsetY
contain the pointer’s position relative
to the listener
Slide 19
Slide 19 text
Pointer Events
1. In app.component.html, add event bindings for the pointer events:
2. In app.component.ts (onPointerMove()), draw the user input:
this.context.fillRect(event.offsetX, event.offsetY, 2, 2);
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint LAB #4
Slide 20
Slide 20 text
Bresenham Line Algorithm
The user may move faster than the
input can be processed
For this case, we need to remember
the previous point and interpolate
the points in between
The Bresenham line algorithm
calculates the missing pixels between
two given points
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
Slide 21
Slide 21 text
Bresenham Line Algorithm
1. At the top of app.component.ts, a field called previousPoint to store the
previous point:
previousPoint?: { x: number, y: number };
2. In onPointerDown(), set the current point as the previous point:
this.previousPoint = { x: event.offsetX, y: event.offsetY };
3. In onPointerUp(), set:
this.previousPoint = undefined;
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint LAB #5
Slide 22
Slide 22 text
Bresenham Line Algorithm
4. In onPointerMove(), call the Bresenham line algorithm with the points:
if (this.previousPoint) {
const currentPoint = { x: event.offsetX, y: event.offsetY };
for (const point of
this.paintService.bresenhamLine(this.previousPoint,
currentPoint)) {
this.context.fillRect(point.x, point.y, 2, 2);
}
this.previousPoint = currentPoint;
}
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint LAB #5
Slide 23
Slide 23 text
Color Selection
For this demo, we will only implement the
brush tool. However, we want to bring in
some color.
A simple method to implement a color
selection is to use the HTML color-type
input element that shows the native color
picker:
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
Slide 24
Slide 24 text
Color Selection
1. In app.component.html, remove the “It works!” line and add:
2. In app.component.ts (onColorChange()), update the context’s fill style
accordingly:
this.context.fillStyle = color.value;
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Paint
LAB #6
Slide 25
Slide 25 text
Paint PWA Capabilities
Progressive
Enhancement
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Agenda
Slide 26
Slide 26 text
für Desktop und Mobile mit Angular (Hands-on)
Progressive Web Apps
Responsive Linkable Discoverable Installable App-like
Connectivity
Independent
Fresh Safe Re-engageable Progressive
Slide 27
Slide 27 text
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Web App
Manifest
Service
Worker
Slide 28
Slide 28 text
Web App Manifest
Distinguishes Web Apps from Websites
JSON-based file containing metadata for
apps only
Apps can be identified by search engines,
app store providers, etc.
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Slide 29
Slide 29 text
manifest.webmanifest
{
"short_name": "Paint",
"name": "Paint Workshop",
"theme_color": "white",
"icons": [{
"src": "icon.png",
"sizes": "512x512"
}],
"start_url": "/index.html",
"display": "standalone",
"shortcuts": [/* … */]
}
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Names
Icons
Display Mode
Shortcuts
Start URL
Theme color (status bar/window bar)
Slide 30
Slide 30 text
Manifest Display Modes
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
browser minimal-ui standalone fullscreen
Slide 31
Slide 31 text
Manifest Icon Purposes
(any)
any context (e.g. app icon)
monochrome
different color requirements
maskable
user agent masks icon as required
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Safe Zone
Windows iOS Android
Slide 32
Slide 32 text
Web App Manifest
1. Stop the npm start command, then run the following command to add PWA
support to the current project:
npm run ng add @angular/pwa
2. In public/manifest.webmanifest,
a) set name and short_name to values of your choice
b) change the theme_color to #000080
c) change the background_color to #808080
3. In index.html, change the theme-color to #000080.
4. Run npm start again.
5. Test manifest in DevTools: F12 > Application > Manifest
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA LAB #7
Slide 33
Slide 33 text
Manifest Shortcuts
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Secondary entrypoints for your
application (e.g., home screen quick
actions, jump lists, …)
Static definition in Web App Manifest
Supported by Google Chrome for
Android, macOS and Windows
Supported by Safari 17.4+ on macOS
Slide 34
Slide 34 text
Web App Manifest
1. In manifest.webmanifest, add (at least) the following shortcut:
"shortcuts": [{
"name": "About Paint",
"short_name": "About",
"description": "Show information about Paint",
"url": "./",
"icons": [{ "src": "assets/icons/icon-512x512.png", "sizes": "512x512" }]
}]
2. Test in DevTools: F12 > Application > Manifest
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
LAB #8
Slide 35
Slide 35 text
Web App Manifest – Chromium Install Criteria
1. Web App is not already installed
2. Meets a user engagement heuristic (user has interacted with origin or viewed the
page for at least 30 seconds)
3. Includes a Web App Manifest that has short_name or name, at least a 192px and
512px icon, a start_url and a display mode of fullscreen, standalone or
minimal-ui
4. Served over HTTPS
5. Service workers
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
https://web.dev/articles/install-criteria
Slide 36
Slide 36 text
Service Worker
JavaScript executed in an own thread,
registered by the website
Acts as a controller, proxy, or interceptor
Has a cache to store responses (for offline
availability and performance)
Can wake up even when the website is
closed and perform background tasks (e.g.,
push notifications or sync)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Slide 37
Slide 37 text
Service Worker
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Service Worker
Internet
Website
HTML/JS
Cache
fetch
Slide 38
Slide 38 text
NgServiceWorker
Angular CLI supports Service Worker
generation by simply adding PWA
support:
ng add @angular/pwa
One-size-fits-all Service Worker
Pre-defined functionality, limited
customizability
PWA
für Desktop und Mobile mit Angular (Hands-on)
Progressive Web Apps
Slide 39
Slide 39 text
Workbox
Toolchain by Google
Includes a CLI
Generates a service worker
implementation from directory
contents (e.g., build output, or our
development directory)
Allows you to modify the service
worker behavior (maximum
flexibility)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Slide 40
Slide 40 text
Service Worker
1. In your console, run: npm run pwa
2. Test in DevTools: F12 > Application > Service Worker
3. Install the app: Address Bar > Install
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
LAB #9
Slide 41
Slide 41 text
Push Notifications
Just as native apps, PWAs can receive
push notifications
Combination of two technologies: Web
Notifications and Push API
Supported by Chrome, Edge, Firefox,
Safari
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Slide 42
Slide 42 text
Service Worker Debugging
More information on installed service
workers can be found on
• about://serviceworker-
internals (Chromium-based
browsers)
• about:serviceworkers (Mozilla
Firefox)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Slide 43
Slide 43 text
Service Worker Debugging
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Slide 44
Slide 44 text
Lighthouse
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
Auditing tool by Google, integrated in
Chrome DevTools
Automatically checks performance
metrics, PWA support, accessibility,
SEO and other best practices and
gives tips on how to improve
Can simulate mobile devices
Slide 45
Slide 45 text
Lighthouse
1. Make sure only one tab/window of your PWA is open
2. Open DevTools: F12 > Lighthouse
3. Make sure to select at least the “Progressive Web App” category
4. Click “Analyze page load”
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
PWA
LAB #10
Slide 46
Slide 46 text
Paint PWA Capabilities
Progressive
Enhancement
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Agenda
Slide 47
Slide 47 text
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Slide 48
Slide 48 text
Project Fugu
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
»Let’s bring the web
back – API by API«
Thomas Steiner, Google
Slide 49
Slide 49 text
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
Contacts
Picker
Screen Wake
Lock API
File System
Access API
Shape
Detection API
Slide 50
Slide 50 text
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
https://goo.gle/fugu-api-tracker
Slide 51
Slide 51 text
Browser
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
navigator.share({ url: 'http://example.com' });
ShareIntent DataTransferManager
…
NSSharingServicePicker
Slide 52
Slide 52 text
File System Access API
Some applications heavily rely on
working with files (e.g. Visual Studio
Code, Adobe Photoshop, …)
File System Access API allows you to
open, save and override files and
directories
Supported by Chrome, Edge
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
Slide 53
Slide 53 text
File System Access API
1. Add the following buttons to the bar in app.component.html (before the
color input):
Open
Save
Copy
Paste
Share
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #11
Slide 54
Slide 54 text
File System Access API
2. Add the following lines at the top of app.component.ts:
readonly fileOptions: FilePickerOptions = {
types: [{
description: 'PNG files',
accept: {'image/png': ['.png']}
}]
};
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #11
Slide 55
Slide 55 text
File System Access API
3. Add the following lines to the save() function:
const blob = await
this.paintService.toBlob(this.canvas().nativeElement);
const handle = await
window.showSaveFilePicker(this.fileOptions);
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #11
Slide 56
Slide 56 text
File System Access API
Add the following code to the open() function:
const [handle] = await
window.showOpenFilePicker(this.fileOptions);
const file = await handle.getFile();
const image = await this.paintService.getImage(file);
this.context.drawImage(image, 0, 0);
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #12
Slide 57
Slide 57 text
Async Clipboard API
Allows reading from/writing to the
clipboard in an asynchronous manner
(UI won’t freeze during long-running
operations)
Reading from the clipboard requires
user consent first (privacy!)
Supported by Chrome, Edge and
Safari and Firefox (plain-text only)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
Slide 58
Slide 58 text
Async Clipboard API
Add the following code to the copy() function:
await navigator.clipboard.write([
new ClipboardItem({ "image/png":
this.paintService.toBlob(this.canvas().nativeElement) }),
]);
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #13
Slide 59
Slide 59 text
Async Clipboard API
const clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
for (const type of clipboardItem.types) {
if (type === 'image/png') {
const blob = await clipboardItem.getType(type);
const image = await this.paintService.getImage(blob);
this.context.drawImage(image, 0, 0);
}
}
}
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #14
Slide 60
Slide 60 text
Web Share API
Allows sharing a title, URL, text, or files
API can only be invoked as a result of a
user action (i.e. a click or keypress)
Supported by Chrome, Edge, Safari and
Firefox (Android only)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
Slide 61
Slide 61 text
Web Share API
const blob = await
this.paintService.toBlob(this.canvas().nativeElement);
const file = new File([blob], 'untitled.png', {type:
'image/png'});
const item = { files: [file] };
if (navigator.canShare(item)) {
await navigator.share(item);
}
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #15
Slide 62
Slide 62 text
File Handling API
Register your PWA as a handler for
file extensions
Requires installing the application
first
Declare supported extensions in Web
App Manifest and add imperative
code to your application logic
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
Slide 63
Slide 63 text
File Handling API
1. Add the following property to your manifest (manifest.webmanifest):
"file_handlers": [{
"action": "/index.html",
"accept": {
"image/png": [".png"]
}
}]
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #16
Slide 64
Slide 64 text
File Handling API
2. Add the following code to ngAfterViewInit() in app.component.ts:
if ('launchQueue' in window) {
window.launchQueue.setConsumer(async params => {
const [handle] = params.files;
if (handle) {
const file = await handle.getFile();
const image = await this.paintService.getImage(file);
ctx.drawImage(image, 0, 0);
}
});
}
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #16
Slide 65
Slide 65 text
File Handling API
3. Rebuild PWA: npm run pwa
Note: Wait for a few seconds and reload the application after opening, as the PWA
needs to fetch the new files first.
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
LAB #16
Slide 66
Slide 66 text
Summary
− Project Fugu helps the web to become more and more capable
− Project Fugu APIs could bring many more app experiences to the web (IDEs,
productivity apps, etc.)
− But: Web is threatened by alternative approaches and platforms, support for
modern Web API varies from platform to platform
− You can make a difference!
− File bugs in browser engine bugtrackers
− File Fugu requests: https://goo.gle/new-fugu-request
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Capabilities
Slide 67
Slide 67 text
Paint PWA Capabilities
Progressive
Enhancement
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Agenda
Slide 68
Slide 68 text
Overview
Use available interfaces and functions of a
system (opposite of Graceful Degradation)
Users with modern, feature-rich browsers get a
better experience
Apps are available on older browsers, but with
limited functionality
Concept: Browser feature support should grow
over time—thereby more users can enjoy an
increasing number of features
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Progressive Enhancement
Slide 69
Slide 69 text
Overview
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(…)
.then(() => /* … */);
}
In JavaScript: check whether an API/feature is available. If yes—use it! Otherwise:
1. Disable the functionality
2. Fall back to an alternative API (if available)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Progressive Enhancement
Slide 70
Slide 70 text
Disabling unsupported features
In app.component.ts, introduce the following check object:
readonly supported = {
open: 'showOpenFilePicker' in window,
} as const;
In app.component.html, disable the open button if the API is unsupported:
Open
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Progressive Enhancement LAB #17
Slide 71
Slide 71 text
Disabling unsupported features
Introduce checks for the remaining APIs:
1. Save: 'showSaveFilePicker' in window
2. Copy: navigator.clipboard && 'write' in navigator.clipboard
3. Paste: navigator.clipboard && 'read' in navigator.clipboard
4. Share: 'canShare' in navigator
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Progressive Enhancement LAB #17
Slide 72
Slide 72 text
Providing an alternative implementation
1. In the save() method of app.component.ts, test for the existence of the
showSaveFilePicker() method on the window object.
2. If the method does not exist, fall back to the following code for save:
const anchor = document.createElement('a');
const url = URL.createObjectURL(blob);
anchor.href = url;
anchor.download = '';
anchor.click();
URL.revokeObjectURL(url);
3. Remove the compatibility check to always enable the button.
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Progressive Enhancement LAB #18
Slide 73
Slide 73 text
Deployment
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Electron/Capacitor
JS
HTML
CSS
.ipa
.exe .app ELF
.apk .appx
Single-Page Application
Capacitor
Electron
Slide 74
Slide 74 text
(Simplified)
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Store Deployments
https://example.com
.appx
.apk
Server
Microsoft
Store
Play
Store
Source
Files
Slide 75
Slide 75 text
Run app on your device
npm run pwa
https://ngrok.com/download
ngrok http 3000
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
LAB #19
Slide 76
Slide 76 text
Q&A
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Slide 77
Slide 77 text
PWAs are now installable, offline-capable and can receive push notifications on all
relevant platforms
Google, Microsoft and Apple are aligned on installable web applications
Project Fugu unlocks more and more capabilities for the web in a secure, privacy-
preserving manner
Big apps like Photoshop and Visual Studio Code prove that the application model
works
Write your apps once, run them anywhere!
Progressive Web Apps
für Desktop und Mobile mit Angular (Hands-on)
Summary
Slide 78
Slide 78 text
Thank you
for your kind attention!
Christian Liebel
@christianliebel
[email protected]