by Gerard Sans | @gerardsans
SANS
GERARD
Spoken at 162 events in 37 countries
Reliable
Storage
Native-like Features
Great User Experience
Offline
Ready
Web App
Manifest
Service
Worker
Security
(HTTPS)
index.html
Cache
Hosting
Service
Worker
OFFLINE
app.js
logo.png
app.js
logo.png
app.js
logo.png
app.js
logo.png
$ ng add @angular/pwa
ngsw-config.json (added)
src/assets/icons/icon-*.png (added)
src/manifest.webmanifest (added)
angular.json (updated)
index.html (updated)
app.module.ts (updated)
src/app.component.ts
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AmplifyDatastore</title>
<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.</noscript>
</body>
</html>
src/app.component.ts
import { ServiceWorkerModule } from '@angular/service-worker';
import { env } from '../environments/environment';
@NgModule({
imports: [
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: env.production
})
],
})
export class AppModule { }
src/app.component.ts
$ ng build --prod
src/app.component.ts
└── dist
├── assets/icons
├── favicon.ico
├── index.html
├── manifest.webmanifest
├── safety-worker.js
├── ngsw.json
└── ngsw-worker.js
$ npm i -g http-server
$ http-server dist/amplify-datastore -o
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
},
{
"name": "assets",
}
]
}
src/app.component.ts
{
"name": "app",
"installMode": "prefetch", // prefetch | lazy
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/*.js"
],
"urls": [
"https://aws-amplify.github.io/images/Logos/Amplify-Logo-White.svg"
]
}
}
src/app.component.ts
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
]
}
}
src/app.component.ts
// <div *ngIf="offline">You are offline.</div>
// app.component.ts
@Component(...)
export class AppComponent implements OnInit {
offline : boolean = false;
ngOnInit() {
merge<boolean>(
fromEvent(window, 'offline').pipe(mapTo(true)),
fromEvent(window, 'online').pipe(mapTo(false)),
of(!navigator.onLine)
).subscribe(offline => this.offline = offline);
}
}
src/app.component.ts