Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Codemotion: Progressive Web Applications (PWAs) - Jorge Ferreiro - @jgferreiro

Codemotion: Progressive Web Applications (PWAs) - Jorge Ferreiro - @jgferreiro

Technical talk for Codemotion about Progressive Web Apps (PWAs), the future of web development.

🔗 Twitter: https://twitter.com/JGFerreiro
🔗 Linkedin: https://www.linkedin.com/in/jgferreiro/

- - -

PWAs are the next revolution in web development. In this workshop, you will understand the main features of a PWA while learning how to create your own PWA in JavaScript with a real world project running React!

You will learn how to create an app with:
• Caching requests: images, CSS, index.html.
• Web Notifications
• Payments Api
• How to setup your app manifest and add to home screen
• Other PWA functionalities.

- - -

Subscribe: https://jorgeferreiro.com/newsletter

on https://www.twitter.com/jgferreiro
on https://www.linkedin.com/in/jgferreiro/
on https://www.instagram.com/jgferreiro/

Jorge Ferreiro

October 24, 2019

More Decks by Jorge Ferreiro

Other Decks in Programming


  1. Progressive Web Apps 101 Jorge Ferreiro (@jgferreiro) www.ferreiro.me

  2. @JGFERREIRO @JGFERREIRO #codemotionpwa How many of you have ever created

    a web app?
  3. @JGFERREIRO @JGFERREIRO #codemotionpwa How many of you know what a

    PWA is?
  4. @JGFERREIRO #CODEMOTIONPWA Frontend @Eventbrite Alumni @Amazon Blogger, DJ, fan of

    musicals Jorge Ferreiro
  5. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA youtube.com/jgferreiro My youtube show:

  6. @JGFERREIRO @JGFERREIRO What are we gonna build today? 0.

  7. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Our first Progressive Web App! ✅ Offline

    mode ✅ Local Notifications ✅ Cache requests ✅ Payments API ❌ Background Sync ❌ IndexedDB Emotion CSS-in-JS

  9. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA github.com/ferreiro/pwa-101 ferreiro/pwa-101 Source code

  10. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Agenda • Motivation • Manifest • Service

    workers • Offline Mode • APIs and advanced topics Important quote
  11. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Audience: Goals Experts on PWA Web devs

    with no experience on PWA Beginners



  15. @JGFERREIRO @JGFERREIRO # What are Progressive Web Apps? 1.

  16. @JGFERREIRO #CODEMOTIONPWA Web applications that adapts the user experience based

    on the device network, device capabilities and user needs Progressive Web Apps (PWAs):
  17. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA PWAs can also have native mobile apps

    cabapabilities (offline mode, push, etc.) Big selling point!
  18. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Using latest browser features when they are

    available Progressive enhancement:
  19. @JGFERREIRO Progressive enhancement: Intuition

  20. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA ๏ Simplified web version ๏ Data save

    mode ๏ Limit access to advanced features Progressive enhancement: Example ๏ High quality media ๏ Advanced Features: Push, background sync, etc. United States Bad 2G connection | Cheap phone 5G connection | High quality phones % Africa
  21. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Progressive enhancement: Simplification if ('feature' in browser)

    { !// Feature is available!!! !// Do something cool with it! } else { !// Party pooper !// Browser does not support this feature !// Change your browser!!... }
  22. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Responsive ' Works offline ⚙ App-like- interactions

    Fresh Safe Discoverable Re-engageable PWA features (Alex Russell Jake Archibald) Durable Linkable Alex Russel “Progressive Web Apps: Escaping Tabs Without Losing Our Soul”
  23. @JGFERREIRO Android rocks! @JGFERREIRO #CODEMOTIONPWA ✅ Web Push ✅ Background

    Sync ✅ PWAs in the Google Play https://www.youtube.com/watch?v=7JDFjeMvxos
  24. @JGFERREIRO @JGFERREIRO Progressive Web Apps in the industry 2.

  25. @JGFERREIRO @JGFERREIRO #codemotionpwa Amazing PWAs in the industry

  26. @JGFERREIRO @JGFERREIRO #codemotionpwa Pinterest increased by 843% new signups y/y

    A one year PWA retrospective
  27. @JGFERREIRO @JGFERREIRO #codemotionpwa Twitter decreased by 70% data consumption 1.

    Twitter Lite case study 2. How we built Twitter Lite
  28. @JGFERREIRO @JGFERREIRO #codemotionpwa Tinder mobile loading time decreased from 11.37s

    to 4.69s

  30. @JGFERREIRO @JGFERREIRO Why Progressive Web Apps? 3.

  31. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Smaller and 1-click install Native apps tend

    to occupy more space. Offline and notifications! Improves user retention and converstions. Adaptative experience Our apps can adapt to any device. Distribution Freedom No need apple store or play store

  33. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Our first Progressive Web App! Emotion CSS-in-JS

    ✅ Offline mode ✅ Local Notifications ✅ Cache requests ✅ Payments API ❌ Background Sync ❌ IndexedDB
  34. @JGFERREIRO @JGFERREIRO Progressive metatags 4.

  35. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Viewport metatag <meta name="viewport" content="width=device-width, initial-scale=1"> mdn:

    Using the viewport meta tag Forces the browser to use real device width
  36. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Theme color <meta name="theme-color" content="#fb8397">

  37. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Apple metatags Apple: Configuring web applications <meta

    name="apple-mobile-web-app-title" content="Pennapps"> <meta name="apple-mobile-web-app-status-bar-style" content="white"> <meta name="apple-mobile-web-app-capable" content="yes">
  38. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA More Apple metatags… icons favicon-generator.org <link rel="apple-touch-icon"

    sizes="57x57" href=“image_57_57.png"> <link rel="apple-touch-icon" sizes="60x60" href="image_60_60.png"> <link rel="apple-touch-icon" sizes="72x72" href="image_72_72.png"> <link rel="apple-touch-icon" sizes="76x76" href="image_76_76.png"> <link rel="apple-touch-icon" sizes="114x114" href="image_114_114.png"> <link rel="apple-touch-icon" sizes="120x120" href="image_120_120.png"> <link rel="apple-touch-icon" sizes="144x144" href="image_144_144.png"> <link rel="apple-touch-icon" sizes="152x152" href="image_152_152.png"> <link rel="apple-touch-icon" sizes="180x180" href="image_180_180.png">
  39. @JGFERREIRO @JGFERREIRO Manifest.json 5.

  40. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA manifest.json is a file that tells the

    browser about your web application and how it should behave when 'installed' https://developers.google.com/web/fundamentals/web-app-manifest
  41. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Create manifest.json "short_name": "Pennapps", "name": "Pennapps agenda",

    "start_url": "/?utm_source=pwa", "display": "standalone", "theme_color": "#ffffff", "background_color": "#ffffff", "scope": "/", "icons": [] { } <link href="/static/manifest.json" rel="manifest">
  42. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA “short_name": "Pennapps", "name": "Pennapps agenda", "start_url": "/?utm_source=pwa",

    "display": "standalone", "theme_color": "#ffffff", "background_color": "#ffffff", "scope": "/", "icons": [] { } { !// 192 for the “home screen icon” "src": "/static/images/pennapps_logo_pwa_192_192.png", "sizes": "192x192", "type": "image/png" }, { !// 512 for splash screen (on Android) "src": "/static/images/pennapps_logo_pwa_512_512.png", "sizes": "512x512", "type": "image/png" } ]
  43. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Manifest.json - display fullscreen No browser UI

    ✅ Videogames standalone Hides standard browser UI elements ✅ Standalone native app minimal-ui Fullscreen display. Minimal UI elements browser Standard browser experience Google: Web App Manifest
  44. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Test your manifest in dev tools

  45. @JGFERREIRO Test your manifest in Lighthouse

  46. @JGFERREIRO @JGFERREIRO Intro to Service Workers 6.

  47. @JGFERREIRO @JGFERREIRO #codemotionpwa A service worker is like a client

    side proxy It gives you control of the cache, and how to respond to requests
  48. @JGFERREIRO @JGFERREIRO #codemotionpwa Service Worker A service worker is a

    JavaScript file that runs separately from the main browser thread
  49. @JGFERREIRO @JGFERREIRO Our first service worker

  50. SERVICE WORKER :: INSTALL CALLBACK self.addEventListener('install', (event) !=> { !//

    Install anything you need here! }) self.addEventListener('fetch', (event) !=> { console.log('I am intercepting network requests!') const url = event.request.url console.log('Requested resource url: ', url) }) Create a new SW.js file
  51. SERVICE WORKER :: REGistering new SW if ('serviceWorker' in navigator)

    { console.log('⭐ Start to register a service worker') navigator.serviceWorker.register('/sw.js') .then((registration) !=> { console.log('SW!::Registration', registration) }) .catch((error) !=> { console.log('SW!::Error registering', error) }); }
  52. @JGFERREIRO @JGFERREIRO #codemotionpwa

  53. @JGFERREIRO @JGFERREIRO Offline mode with Cache API 7.

  54. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Offline mode? We need a cache! We

    need a bunch of cached resources, downloaded in the client’s browser Cached resources in the browser
  55. @JGFERREIRO #CODEMOTIONPWA Cache API is a key-value storage mechanism for

    requests<>responses pairs
  56. @JGFERREIRO #CODEMOTIONPWA Cache API gives programmatic control over caching assets

    inside a service worker
  57. @JGFERREIRO @JGFERREIRO #codemotionpwa

  58. @JGFERREIRO @JGFERREIRO Cache Hello World 7.1

  59. @JGFERREIRO @JGFERREIRO #codemotionpwa caches.open() Returns a Promise with the Cache

    object CacheStorage API https://developer.mozilla.org/en- US/docs/Web/API/CacheStorage
  60. @JGFERREIRO @JGFERREIRO #codemotionpwa Cache object Cache.add(request) Cache.addAll([request]) Cache.put(request, response) Cache.delete(request,

    options) Cache.match(request, options) Cache.matchAll(request, options) https://developer.mozilla.org/en- US/docs/Web/API/Cache (Same as fetch() + put()) Request object or a URL fetch(new Request(“/image.jpg”))
  61. CACHE API :: HELLO WORLD const cacheNameVersion = 'resources-v1' self.addEventListener('install',

    () !=> { }) caches.open(cacheNameVersion) .then((cache) !=> { cache.add("index.html") cache.add("client.bundle.js") }) .catch((error) !=> { !// Error opening the cache :/ })
  62. @JGFERREIRO @JGFERREIRO #codemotionpwa Check cached resources

  63. @JGFERREIRO @JGFERREIRO #codemotionpwa Check cached resources

  64. @JGFERREIRO @JGFERREIRO #codemotionpwa Check cache size

  65. @JGFERREIRO @JGFERREIRO Caching critical assets 7.2

  66. @JGFERREIRO @JGFERREIRO #codemotionpwa A critical asset? Things needed to run

    your app without internet connection.
  67. @JGFERREIRO @JGFERREIRO #codemotionpwa event.waitUntil() Service worker will stay in “install”

    mode, until the promise is resolved ✅ Are all assets cached? Then Service Worker is installed! ❌ Error caching critical assets? Service worker not installed.
  68. CACHE API :: REQUIRING CRITICAL ASSETs const cacheVersion = 'version-1'

    const noCriticalAssets = [‘foo.css'] const criticalAssets = ['/index.html', ‘/client.bundle.js'] function cacheAssets() { return caches.open(cacheVersion) .then((cache) !=> { cacheNoCriticalAssets(cache) return cacheCriticalAssets(cache) }) } function cacheCriticalAssets (cache) { return cache.addAll(criticalAssets) } function cacheNoCriticalAssets(cache) { cache.addAll(noCriticalAssets) } self.addEventListener('install', (event) !=> { event.waitUntil(cacheAssets()) }) This return does the magic! If failure on this promise, then waitUntil will fail
  69. @JGFERREIRO @JGFERREIRO #codemotionpwa Check cached resources

  70. @JGFERREIRO @JGFERREIRO #codemotionpwa Check cached resources

  71. @JGFERREIRO @JGFERREIRO #codemotionpwa Check cache size

  72. @JGFERREIRO @JGFERREIRO Removing old cache resources 7.3


  74. CACHE API :: REMOVING CACHED ASSETS self.addEventListener('install', (event) !=> {

    !// Add assets to the service worker cache }) self.addEventListener('activate', (event) !=> { !// Remove cached assets from previous version !// using caches.delete(). }) Make sure to remove cached ASSETS!
  75. @JGFERREIRO @JGFERREIRO Fetch image or placeholder 7.4


  77. CACHE API :: Fetch image or placeholder self.addEventListener('fetch', (event) !=>

    { const acceptHeader = event.request.headers.get('accept') if (acceptHeader.includes('image')) { return event.respondWith( fetchImageOrPlaceholder(event) ) } })
  78. CACHE API :: Fetch image or placeholder function fetchImageOrPlaceholder(fetchEvent) {

    return fetch(fetchEvent.request) .then((response) !=> { if (!response.ok) { throw Error(‘Can not download from server…’) } return response }) .catch(() !=> { !// NB: Return placeholder. return caches.match(placeholderImage, { cacheName: cacheVersion }) }) } const placeholderImage = '/images/placeholder.jpg'
  79. @JGFERREIRO @JGFERREIRO Network request with cache backup 7.5


  81. CACHE API :: Fetch image or placeholder self.addEventListener('fetch', (event) !=>

    { const acceptHeader = event.request.headers.get('accept') if (acceptHeader.includes('image')) { return event.respondWith( fetchImageOrPlaceholder(event) ) } })
  82. CACHE API :: Fetch image or placeholder function fetchImageOrFallback(event) {

    return fetch(event.request) READ CacheStorage .then((response) !=> { if (!response.ok) { throw Error('Can not download image from server') } caches.open(cacheVersion).then(function(cache) { !// Cache in background cache.put(event.request, response) }) return response.clone() !// NB: Can't reuse responses twice: bit.ly/response-clone }) .catch(() !=> { return caches.match(fetchEvent.request).catch(function() { !// try to get cached return caches.match('/images/placeholder.jpg', { !// Return placeholder cacheName: cacheVersion }) }) }) }
  83. @JGFERREIRO @JGFERREIRO #codemotionpwa Further reading:

  84. @JGFERREIRO @JGFERREIRO Other cool APIs and concepts 8.

  85. @JGFERREIRO Local notification

  86. @JGFERREIRO Payments API

  87. @JGFERREIRO Other advanced concepts Web Push Notifications using VAPID The

    App Shell Model
 (see also The PRPL Pattern) Background Sync IndexedDB
  88. @JGFERREIRO - [email protected] Q&A!

  89. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Who to follow? Jake Archibald Google @jaffathecake

    Alex Russell Chrome Team @slightlylate Sarah Clark Google @a_bowl_of_stars Pete LePage Google @petele Dominick Ng Chrome PWA @dominickng Scott Domes Indeed @scottdomes Kenneth C. Intel @kennethrohde Henrik Joreteg Consultant @HenrikJoreteg Charlie Croom Twitter @CharlieCroom Monica Dinculescu Polymer @notwaldorf
  90. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Action plan 1. Fork “pwa 101” repo

    and start it locally 2. Re-read this presentation, and open some of the links in the resources 3. Execute each of the steps to add progressive enhancement to your app
  91. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA Resources 1. Google I/O 2014 - Bridging

    the gap between the web and apps 2. How we built Twitter Lite 3. Twitter Lite and High Performance React Progressive Web Apps at Scale 4. Google workbox 5. Payment request 6. Frontend masters: Progressive web apps 7. Background sync 8. Google: Progressive web apps YouTube traiing
  92. @JGFERREIRO @JGFERREIRO #CODEMOTIONPWA github.com/ferreiro/pwa-101 ferreiro/pwa-101 Source code

  93. @JGFERREIRO @JGFERREIRO #codemotionpwa Get the slides: I’ll post it on

    my twitter.com/jgferreiro
  94. @JGFERREIRO #CODEMOTIONPWA PWA are the future of mobile apps. Start

    learning today!
  95. Thanks @jgferreiro [email protected] #codemotionPWA!