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
Tweet

More Decks by Jorge Ferreiro

Other Decks in Programming

Transcript

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

    View full-size slide

  2. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    How many of you have
    ever created a web app?

    View full-size slide

  3. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    How many of you know
    what a PWA is?

    View full-size slide

  4. @JGFERREIRO #CODEMOTIONPWA
    Frontend @Eventbrite
    Alumni @Amazon
    Blogger, DJ, fan of musicals
    Jorge Ferreiro

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  7. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Our first Progressive Web App!
    ✅ Offline mode
    ✅ Local Notifications
    ✅ Cache requests
    ✅ Payments API
    ❌ Background Sync
    ❌ IndexedDB
    Emotion CSS-in-JS

    View full-size slide

  8. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA

    View full-size slide

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

    View full-size slide

  10. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Agenda
    • Motivation
    • Manifest
    • Service workers
    • Offline Mode
    • APIs and advanced topics
    Important quote

    View full-size slide

  11. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Audience: Goals
    Experts on PWA
    Web devs with no
    experience on PWA
    Beginners

    View full-size slide

  12. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Questions to Fran :)

    View full-size slide

  13. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    #CODEMOTIONPWA
    @JGFERREIRO

    View full-size slide

  14. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA

    View full-size slide

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

    View full-size slide

  16. @JGFERREIRO #CODEMOTIONPWA
    Web applications that adapts the
    user experience based on the device
    network, device capabilities and
    user needs
    Progressive Web Apps (PWAs):

    View full-size slide

  17. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    PWAs can also have native
    mobile apps cabapabilities
    (offline mode, push, etc.)
    Big selling point!

    View full-size slide

  18. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Using latest browser features
    when they are available
    Progressive enhancement:

    View full-size slide

  19. @JGFERREIRO
    Progressive enhancement: Intuition

    View full-size slide

  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

    View full-size slide

  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!!...
    }

    View full-size slide

  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”

    View full-size slide

  23. @JGFERREIRO
    Android rocks!
    @JGFERREIRO #CODEMOTIONPWA
    ✅ Web Push
    ✅ Background Sync
    ✅ PWAs in the Google Play
    https://www.youtube.com/watch?v=7JDFjeMvxos

    View full-size slide

  24. @JGFERREIRO
    @JGFERREIRO
    Progressive Web
    Apps in the industry
    2.

    View full-size slide

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

    View full-size slide

  26. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Pinterest increased by
    843% new signups y/y
    A one year PWA retrospective

    View full-size slide

  27. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Twitter decreased by 70%
    data consumption
    1. Twitter Lite case study
    2. How we built Twitter Lite

    View full-size slide

  28. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Tinder mobile loading time
    decreased from 11.37s to 4.69s

    View full-size slide

  29. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  32. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Let’s build our first
    PWA!

    View full-size slide

  33. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Our first Progressive Web App!
    Emotion CSS-in-JS
    ✅ Offline mode
    ✅ Local Notifications
    ✅ Cache requests
    ✅ Payments API
    ❌ Background Sync
    ❌ IndexedDB

    View full-size slide

  34. @JGFERREIRO
    @JGFERREIRO
    Progressive
    metatags
    4.

    View full-size slide

  35. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Viewport metatag
    content="width=device-width, initial-scale=1">
    mdn: Using the viewport meta tag
    Forces the browser to use real device width

    View full-size slide

  36. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Theme color

    View full-size slide

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




    View full-size slide

  38. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    More Apple metatags… icons
    favicon-generator.org









    View full-size slide

  39. @JGFERREIRO
    @JGFERREIRO
    Manifest.json
    5.

    View full-size slide

  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

    View full-size slide

  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": []
    {
    }

    View full-size slide

  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"
    }
    ]

    View full-size slide

  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

    View full-size slide

  44. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA
    Test your manifest in dev tools

    View full-size slide

  45. @JGFERREIRO
    Test your manifest in Lighthouse

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  48. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Service
    Worker
    A service worker is a JavaScript file
    that runs separately from the main
    browser thread

    View full-size slide

  49. @JGFERREIRO
    @JGFERREIRO
    Our first service
    worker

    View full-size slide

  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

    View full-size slide

  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)
    });
    }

    View full-size slide

  52. @JGFERREIRO
    @JGFERREIRO #codemotionpwa

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  55. @JGFERREIRO #CODEMOTIONPWA
    Cache API is a key-value
    storage mechanism for
    requests<>responses pairs

    View full-size slide

  56. @JGFERREIRO #CODEMOTIONPWA
    Cache API gives programmatic
    control over caching assets
    inside a service worker

    View full-size slide

  57. @JGFERREIRO
    @JGFERREIRO #codemotionpwa

    View full-size slide

  58. @JGFERREIRO
    @JGFERREIRO
    Cache Hello World
    7.1

    View full-size slide

  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

    View full-size slide

  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”))

    View full-size slide

  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 :/
    })

    View full-size slide

  62. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Check cached resources

    View full-size slide

  63. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Check cached resources

    View full-size slide

  64. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Check cache size

    View full-size slide

  65. @JGFERREIRO
    @JGFERREIRO
    Caching critical
    assets
    7.2

    View full-size slide

  66. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    A critical asset?
    Things needed to run your app
    without internet connection.

    View full-size slide

  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.

    View full-size slide

  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

    View full-size slide

  69. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Check cached resources

    View full-size slide

  70. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Check cached resources

    View full-size slide

  71. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Check cache size

    View full-size slide

  72. @JGFERREIRO
    @JGFERREIRO
    Removing old
    cache resources
    7.3

    View full-size slide

  73. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA

    View full-size slide

  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!

    View full-size slide

  75. @JGFERREIRO
    @JGFERREIRO
    Fetch image or
    placeholder
    7.4

    View full-size slide

  76. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA

    View full-size slide

  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)
    )
    }
    })

    View full-size slide

  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'

    View full-size slide

  79. @JGFERREIRO
    @JGFERREIRO
    Network request
    with cache backup
    7.5

    View full-size slide

  80. @JGFERREIRO
    @JGFERREIRO #CODEMOTIONPWA

    View full-size slide

  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)
    )
    }
    })

    View full-size slide

  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
    })
    })
    })
    }

    View full-size slide

  83. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Further reading:

    View full-size slide

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

    View full-size slide

  85. @JGFERREIRO
    Local notification

    View full-size slide

  86. @JGFERREIRO
    Payments API

    View full-size slide

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

    (see also The PRPL Pattern)
    Background Sync
    IndexedDB




    View full-size slide

  88. @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

    View full-size slide

  89. @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

    View full-size slide

  90. @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

    View full-size slide

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

    View full-size slide

  92. @JGFERREIRO
    @JGFERREIRO #codemotionpwa
    Get the slides:
    I’ll post it on my twitter.com/jgferreiro

    View full-size slide

  93. @JGFERREIRO #CODEMOTIONPWA
    PWA are the future of
    mobile apps. Start learning
    today!

    View full-size slide

  94. Thanks
    @jgferreiro
    [email protected]
    #codemotionPWA!

    View full-size slide