Maxim Salnikov
@webmaxru
Building a
My App
Maxim Salnikov
-
PWA Slack organizer
-
PWA Oslo / PWA London meetups organizer
-
ngVikings conference organizer
-
Google Dev Expert in Angular
Azure Developer Technical Lead at Microsoft
What is PWA at all?
Progressive web apps use modern web APIs along with traditional progressive enhancement strategy to create cross-platform web applications.
These apps work everywhere and provide several features that give them the same user experience advantages as native apps.
UX advantages?
Smart networking + Offline
Proper app experience
Staying notified
Other cool things
}
Service Worker API
Web App Manifest
works everywhere*
* but not everything**
natively
** use progressive enhancement strategy
Platforms / browsers support
Support: detailed
Web API Confluence
APIs actively used in PWAs
-
Service Worker API
-
Cache API
-
IndexedDB
-
Fetch
-
Clients API
-
Broadcast Channel API
-
Push API
-
Notifications API
-
Local Storage
-
Session Storage
-
XMLHttpRequest
-
DOM
Not available in service worker:
Even more capable web
-
Writable Files API
-
WebHID API
-
Scheduled Task / Notification API
-
Web Share Target API
-
Wake Lock API
-
Cookie Store API
-
User Idle Detection API
-
...
Project Fugu
Minimum viable PWA
=
+
Application shell
Web App Manifest
Fast, responsive, mobile-first
Served via HTTPS
Let's build an App Shell
My App
-
Define the set of assets required to show the minimum viable UI
Service worker
-
install: put the assets into Cache Storage
-
activate: clear Cache Storage from the previous app version assets
-
fetch: if the asset is in Cache Storage serve it from there. Otherwise — download and serve it (and cache it)
Build time
-
Register service worker the way it does not affect the app loading performance
Website/webapp
Service Worker
Service Worker 101
Logically
Physically
-file(s)
App
Service-worker
Browser/OS
Event-driven worker
Cache
fetch
push
sync
Lifecycle
'install'
Parsed
Installing
Activating
Redundant
'activate'
Waiting
Active
Managing cache
self.addEventListener('install', (event) => {
// Put app's html/js/css to cache
})
self.addEventListener('activate', (event) => {
// Wipe previous version of app files from cache
})
In the real world
-
Can't add opaque responses directly
-
Redirected requests should be managed
-
Always creating a new version of cache and deleting the old one is not optimal
-
Control over cache size is required
-
Cache invalidation for runtime caching is complex
-
...
Intercepting requests
self.addEventListener('fetch', (event) => {
if (event.request.url.indexOf('/api') != -1) {
event.respondWith(
// Network-First Strategy
)
} else {
event.respondWith(
// Cache-First Strategy
)
}
})
In the real world
-
All kinds of fallbacks needed for the strategies
-
There are more complex strategies like Stale-While-Revalidate
-
Good to have routing
-
Good to have the possibility to provide some extra settings for different resource groups
-
...
Making an "app" from the website
=
+
Application shell
Web App Manifest
Fast, responsive, mobile-first
Served via HTTPS
For the manual install on Chrome 72 on Mac
-
Not already installed
-
Meets engagement heuristics
-
Proper Web App Manifest
-
Service worker with fetch event
-
Not "prefer related applications"
Installation criteria
-
short_name or name
-
icons must include a 192px and a 512px sized icons
-
start_url
-
display must be one of: fullscreen, standalone, or minimal-ui
MVP Web App Manifest
Tools & libraries
-
Implementing complex algorithms
-
Adopting best practices
-
Focusing on YOUR task
-
Following specifications updates
-
Handling edge cases
Tools help with
Coding time
-
Application shell
-
Runtime caching
-
Replaying failed network requests
-
Offline Google Analytics
-
Broadcasting updates
-
Registration helper
Have our own service worker!
Working modes
-
Workbox CLI
-
Webpack plugin
-
Node module
# Installing the Workbox Node module
$ npm install workbox-build --save-dev
Also installs all Workbox libraries via dependencies
Build script
// We will use injectManifest mode
const {injectManifest} = require('workbox-build')
// Sample configuration with the basic options
var workboxConfig = {...}
// Calling the method and output the result
injectManifest(workboxConfig).then(({count, size}) => {
console.log(`Generated ${workboxConfig.swDest},
which will precache ${count} files, ${size} bytes.`)
})
workbox-build-inject.js
Build script configuration
// Sample configuration with the basic options
var workboxConfig = {
globDirectory: 'dist/angular-pwa/',
globPatterns: [
'**/*.{txt,png,ico,html,js,json,css}'
],
swSrc: 'src/service-worker.js',
swDest: 'dist/angular-pwa/service-worker.js'
}
workbox-build-inject.js
Source service worker
// Importing Workbox itself from Google CDN
importScripts('https://googleapis.com/.../workbox-sw.js');
// Precaching and setting up the routing
workbox.precaching.precacheAndRoute([])
src/service-worker.js
1
2
Precaching manifest
[
{
"url": "index.html",
"revision": "34c45cdf166d266929f6b532a8e3869e"
},
{
"url": "favicon.ico",
"revision": "b9aa7c338693424aae99599bec875b5f"
},
...
]
Build flow integration
{
"scripts": {
"build-pwa": "ng build --prod &&
node workbox-build-inject.js"
}
}
package.json
Demo time
Runtime caching
Routes and strategies
workbox.routing.registerRoute(
new RegExp('/api/'),
new workbox.strategies.NetworkFirst()
);
src/service-worker.js
workbox.routing.registerRoute(
new RegExp('/images/'),
new workbox.strategies.CacheFirst({
plugins: [...]
})
);
Strategies
-
CacheFirst
-
CacheOnly
-
NetworkFirst
-
NetworkOnly
-
StaleWhileRevalidate
Plugins
-
Expiration
-
CacheableResponse
-
BroadcastUpdate
-
BackgroundSync
-
...your own plugin?
Sample code
-
1900+ developers
-
Major browsers/frameworks/libs reps
Thank you!
Maxim Salnikov
@webmaxru
Questions?
Maxim Salnikov
@webmaxru
Building a Progressive Web Application
By Maxim Salnikov
Building a Progressive Web Application
In part one of this three-part hands-on coding series, we’ll look at why the idea of Progressive Web Apps has become so popular, which APIs are in the game, and where (browsers/platforms) PWAs work. We start by answering these questions and then dive directly into coding a minimum viable PWA to understand the foundations of Service Workers and to make sure that it’s cool to have some helper tools there. Feel free to either just watch, or code along too!
- 1,439