One PWA Solution
Maxim Salnikov
@webmaxru
Many Frameworks –
How to build a framework-agnostic PWA?
Using the power of your favorite framework
Maxim Salnikov

-
PWAdvocate
-
PWA Oslo / PWA London meetups organizer
-
ngVikings and Mobile Era conferences organizer
-
Google Dev Expert in Web Technologies

Azure Developer Relations 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.

works everywhere*
* but not everything**
natively
** use progressive enhancement strategy
What do frameworks give us?

=
+
Application shell
Web App Manifest
Fast, responsive, mobile-first
Served via HTTPS
The most popular frameworks



React
SW library
Out-of-the-box
Configuring
Extending
Workbox
Web App Manifest
App Shell
$ create-react-app my-react-pwa
serviceWorker.unregister();
serviceWorker.register();

Vue
SW library
Out-of-the-box
Configuring
Extending
Workbox
Web App Manifest
App Shell
Runtime Caching
$ vue add pwa

Angular
SW library
Out-of-the-box
Configuring
Extending
Angular
Service Worker
Web App Manifest
App Shell
Runtime Caching
Push Notifications
Update Flow
$ ng add @angular/pwa
Built-in PWA support
Pros
Cons
-
Seamless integration
-
Easy to start
-
Limited configuration options
-
Difficult to impossible to extend
-
Challenging to add to the existing app
How many frameworks do we use
Requirements
-
Automation of the main service worker tasks
-
Framework-agnostic
-
CI/CD-friendly
-
Full control and flexibility
-
Extensibility
Let's build an App shell
My App
-
Define assets
-
Put in the cache
-
Serve from the cache
-
Manage versions
}
Service worker
Logically
Physically
-file(s)
App
Service worker
Browser/OS
Event-driven worker
Cache
fetch
push
sync
Own service worker
self.addEventListener('install', event => {
// Use Cache API to cache html/js/css
})
self.addEventListener('activate', event => {
// Clean the cache from the obsolete versions
})
self.addEventListener('fetch', event => {
// Serve assets from cache or network
})
handmade-service-worker.js
It's only partially a joke
Because...
Redirects?
Fallbacks?
Opaque response?
Versioning?
Cache invalidation?
Spec updates?
Cache storage space?
Variable asset names?
Feature detection?
Minimal required cache update?
Caching strategies?
Routing?
Fine-grained settings?
Kill switch?
I see the old version!!!
-
Application shell
-
Runtime caching
-
Replaying failed network requests
-
Offline Google Analytics
-
Broadcasting updates
While having our own service worker
Working modes
-
Workbox CLI
-
Webpack plugin
-
Node module
# Installing the Workbox Node module
$ npm install workbox-build --save-dev
Configuration
...
var workboxConfig = {
globDirectory: 'dist/',
globPatterns: [
'**/*.{txt,png,ico,html,js,json,css}'
],
swSrc: 'src/workbox-service-worker.js',
swDest: 'dist/sw.js'
}
...
workbox-build.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/workbox-service-worker.js

Caching, serving, managing versions
Build service worker
// 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.js
Build flow integration
{
"scripts": {
"build-pwa": "npm run build-app &&
node workbox-build.js"
}
}
package.json
App build files
App shell file list
Service worker file
Service worker can do more!
// App shell
workbox.precaching.precacheAndRoute([])
// Runtime caching
workbox.routing.registerRoute(
/(http[s]?:\/\/)?([^\/\s]+\/)api/,
workbox.strategies.networkFirst()
)
// Push notifications
self.addEventListener('push', (event) => {...})
src/workbox-service-worker.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js')
}
Service worker registration
Requirements
-
Feature detection
-
Registration after app fully loaded and UI rendered
-
Hook into service worker update event
There is a new version of the app is available. Click here to refresh.
-
Was the service worker updated?
-
Was the app itself updated?
Using workbox-window
import { Workbox } from 'workbox-window'
// For Angular
platformBrowserDynamic().bootstrapModule(AppModule)
.then( () => {
if ('serviceWorker' in navigator) {
const wb = new Workbox('service-worker.js');
// Event listeners...
wb.register();
}
})
main.js
$ npm install workbox-window
Was service worker file updated?
wb.addEventListener('installed', event => {
if (event.isUpdate) {
// Show "Newer version is available. Refresh?" prompt
} else {
// Optionally: show "The app is offline-ready" toast
}
});
main.js
workbox.core.skipWaiting()
workbox.core.clientsClaim()
src/workbox-service-worker.js
Must have!
Summary
-
PWA idea moves Web Platform forward
-
Popular frameworks embrace it and have official plugins
-
Creating your own service worker might be tricky
-
But extending it by Workbox functionality could be a good option
Try it today!
-
2000+ developers
-
Major browsers/frameworks/libs reps
Thank you!
Maxim Salnikov
@webmaxru
Questions?
Many frameworks - one PWA solution
By Maxim Salnikov
Many frameworks - one PWA solution
There is no doubt that 2018 is the year when Progressive Web Apps will get the really broad adoption and recognition by all the involved parties: browser vendors (finally, all the major ones), developers, users. How does PWA concept play with YOUR favorite framework? React, Angular, Vue, #FrameworkOfTheWeek? In my technical session we’ll check what major frameworks creators prepared for us regarding scaffolding / adding PWA features (spoiler: only basic features), and switch to Workbox. We’ll see that Workbox is a library providing many sophisticated service worker features in a simple, developer-friendly form. Also, we’ll talk about another advantage of Workbox - the flexibility: you build your own service worker and automate some tasks using this library. As the outcome, you’ll be ready to make a production-ready PWA from the app built on any framework.
- 3,513