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

Pennapps hackathon - Workshop: Progressive Web Apps, the future of web development - University of Pennsylvania

Pennapps hackathon - Workshop: Progressive Web Apps, the future of web development - University of Pennsylvania

📹 Video: https://www.youtube.com/watch?v=de1xiqz-BTE
🔗 Twitter: https://twitter.com/JGFerreiro
🔗 Linkedin: https://www.linkedin.com/in/jgferreiro/

Progressive Web Apps is a term that Google created in 2015. Representing the next revolution in web development, PWAs enable more reliable, faster and engaging user experiences while also incorporating mobile app functionalities into websites. These and other features lead many engineers to believe that PWA’s are the future of web development.

I run this workshop at the University of Pennsylvania for Pennapps. We created a progressive web app with the following functionalities:

- Offline mode
- Caching requests: images, CSS, index.html.
- Local Notifications
- Payments API
- How to set up your app manifest
- Add to the home screen

- - -

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 08, 2019
Tweet

More Decks by Jorge Ferreiro

Other Decks in Programming

Transcript

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

    View Slide

  2. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Twitter increases +75%
    tweets sent in their new
    Progressive Web app

    View Slide

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

    View Slide

  4. @JGFERREIRO #PENNPWA
    PENNAPPS MADRID

    "✈$

    View Slide

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

    View Slide

  6. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Agenda
    1. What, why and the industry
    2. Metadata + manifest
    3. Service workers
    4. Cache API
    5. Web Payments
    6. Local Notifications
    7. Action items
    Important quote

    View Slide

  7. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    #PWAPENN
    @JGFERREIRO

    View Slide

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

    View Slide

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

    View Slide

  10. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    github.com/ferreiro/pwa-101
    ferreiro/pwa-101
    Source code

    View Slide

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

    View Slide

  12. @JGFERREIRO
    @JGFERREIRO
    ' What are
    Progressive Web
    Apps?
    1.

    View Slide

  13. @JGFERREIRO #PENNPWA
    Progressive Web Apps (PWAs) are
    web applications with native
    mobile apps capabilities

    View Slide

  14. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    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 Slide

  15. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Using latest browser features
    when they are available, and
    adapt the user experience
    Progressive enhancement:

    View Slide

  16. @JGFERREIRO
    Progressive enhancement: Intuition

    View Slide

  17. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    ๏ 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
    2
    Africa

    View Slide

  18. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    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 Slide

  19. @JGFERREIRO
    @JGFERREIRO
    Why Progressive
    Web Apps?
    2.

    View Slide

  20. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Distribution Freedom
    No need apple store or play store
    5 Key Benefits of Progressive Web Apps
    Push notifications
    Parity feature with Native. Re-engaging users
    No install required
    A matter of seconds to have them installed
    Smaller
    Native apps tend to occupy more space.
    Offline!
    Improves user retention and converstions.
    Why?

    View Slide

  21. @JGFERREIRO
    @JGFERREIRO
    PWAs in the
    industry
    3.

    View Slide

  22. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Twitter
    -70% data consumption
    +65% increase in pages per session
    +75% increase in Tweets sent
    How we built Twitter Lite

    View Slide

  23. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Alibaba
    +76% conversions
    4X higher interaction rate from Add
    to Homescreen
    https://developers.google.com/web/showcase/2016/alibaba

    View Slide

  24. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Starbucks
    +12% growth on orders w/w (May 2018)
    Nearly doubled daily & monthly active
    users
    Google I/O 18’

    View Slide

  25. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Tinder
    Loading time: 11.37s to 4.69s
    90% smaller than Android

    View Slide

  26. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Tinder

    View Slide

  27. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Pinterest
    A one year PWA retrospective
    +401% number of pins
    +103% active users y/y on mobile web
    +843% new signups y/y

    View Slide

  28. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Pinterest
    A one year PWA retrospective
    +401% number of pins
    +103% active users y/y on mobile web
    +843% new signups y/y

    View Slide

  29. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Let’s build our first
    PWA!

    View Slide

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

    View Slide

  31. @JGFERREIRO
    @JGFERREIRO
    Progressive
    metatags
    4.

    View Slide

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

    View Slide

  33. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Theme color

    View Slide

  34. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Apple metatags
    Apple: Configuring web applications




    View Slide

  35. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    More Apple metatags… icons
    favicon-generator.org









    View Slide

  36. @JGFERREIRO
    @JGFERREIRO
    Manifest.json
    5.

    View Slide

  37. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    manifest.json is a configuration
    file to tell the browser how your
    should behave once installed

    View Slide

  38. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    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 Slide

  39. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    “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 Slide

  40. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    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 Slide

  41. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Test your manifest in dev tools

    View Slide

  42. @JGFERREIRO
    Test your manifest in Lighthouse

    View Slide

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

    View Slide

  44. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    A service worker is a JavaScript
    file that runs separately from the
    main browser thread

    View Slide

  45. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

  46. @JGFERREIRO
    @JGFERREIRO
    Our first service
    worker

    View Slide

  47. 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 Slide

  48. SERVICE WORKER :: INSTALL CALLBACK
    self.addEventListener('install', (event) !=> {
    !// Install anything you need here!
    })

    View Slide

  49. SERVICE WORKER :: FETCH CALLBACK
    self.addEventListener('fetch', (event) !=> {
    console.log('I am intercepting network requests!')
    const url = event.request.url
    console.log('Requested resource url: ', url)
    })

    View Slide

  50. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

  55. @JGFERREIRO
    @JGFERREIRO
    Caching critical
    assets
    7.1

    View Slide

  56. CACHE API :: HELLO WORLD
    const cacheNameVersion = 'resources-v1'
    caches.open(cacheNameVersion)
    .then((cache) !=> {
    !// Do something cool with the cache
    })
    .catch((error) !=> {
    !// Error opening the cache :/
    })

    View Slide

  57. CACHE API :: HELLO WORLD
    const cacheNameVersion = 'resources-v1'
    self.addEventListener('install', () !=> {
    caches.open(cacheNameVersion)
    .then((cache) !=> {
    !// Do something cool with the cache
    })
    .catch((error) !=> {
    !// Error opening the cache :/
    })
    })

    View Slide

  58. CACHE API :: REQUIRING CRITICAL ASSETs
    const cacheVersion = 'version-1'
    const criticalAssets = ['/index.html', '/client.bundle.js']
    self.addEventListener('install', (event) !=> {
    event.waitUntil(cacheAssets())
    })
    function cacheAssets() {
    return caches.open(cacheVersion)
    .then((cache) !=> {
    cacheNoCriticalAssets(cache)
    return cacheCriticalAssets(cache)
    })
    }
    function cacheCriticalAssets (cache) {
    return cache.addAll(criticalAssets)
    }
    function cacheNoCriticalAssets(cache) {
    cache.add('./foo.css')
    }

    View Slide

  59. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    event.waitUntil
    Service worker will stay in “install”
    mode, until waitUntil is resolved

    If the resolved promise fails, it will
    not install anything…

    View Slide

  60. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Check cached resources

    View Slide

  61. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Check cached resources

    View Slide

  62. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Check cache size

    View Slide

  63. @JGFERREIRO
    @JGFERREIRO
    Removing old
    cache resources
    7.2

    View Slide

  64. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

  65. CACHE API :: REMOVING CACHED ASSETS
    self.addEventListener('install', (event) !=> {
    !// Add assets to the service worker cache
    })
    self.addEventListener('activated', (event) !=> {
    !// Remove cached assets from previous version
    })
    Make sure to remove cached ASSETS!

    View Slide

  66. @JGFERREIRO
    @JGFERREIRO
    Fetch image or
    placeholder
    7.3

    View Slide

  67. 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 Slide

  68. CACHE API :: Fetch image or placeholder
    function fetchImageOrPlaceholder(fetchEvent) {
    return fetch(fetchEvent.request, {
    mode: 'no-cors'
    })
    .then((response) !=> {
    if (!response.ok) {
    throw Error(‘Can not download from server…’)
    }
    return response
    })
    .catch(() !=> {
    !// NB: Return placeholder.
    return caches.match(PLADEHOLDER_IMAGE, {
    cacheName: cacheVersion
    })
    })
    }

    View Slide

  69. CACHE API :: Fetch image or placeholder
    function fetchImageOrPlaceholder(fetchEvent) {
    return fetch(fetchEvent.request, {
    mode: 'no-cors'
    })
    .then((response) !=> {
    if (!response.ok) {
    throw Error(‘Can not download from server…’)
    }
    return response
    })
    .catch(() !=> {
    !// NB: Return placeholder.
    return caches.match(PLADEHOLDER_IMAGE, {
    cacheName: cacheVersion
    })
    })
    }

    View Slide

  70. @JGFERREIRO
    @JGFERREIRO
    Network with
    cache backup
    7.4

    View Slide

  71. 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 Slide

  72. CACHE API :: Fetch image or placeholder
    function fetchImageOrFallback(fetchEvent) {
    return fetch(fetchEvent.request, {mode: ‘no-cors’})
    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(fetchEvent.request, response)
    })
    return response.clone() !// NB: We can't reuse responses twice
    })
    .catch(() !=> {
    return caches.match(fetchEvent.request).catch(function() { !// try to get cached
    return caches.match(PLADEHOLDER_IMAGE, { !// Return placeholder
    cacheName: cacheVersion
    })
    })
    })
    }

    View Slide

  73. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Further reading:

    View Slide

  74. @JGFERREIRO
    @JGFERREIRO
    Web
    Payments API
    8.

    View Slide

  75. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

  76. Web payments api :: REQUEST OBJECT
    const request = new PaymentRequest(methods, details, options)
    PAYMENT REQUEST CONSTRUCTOR
    const methods = [{
    supportedMethods: 'basic-card',
    data: { supportedNetworks: [ 'visa', 'mastercard' ] }
    }]
    const details = {
    displayItems: [{
    label: 'Computer to mine bitcoin',
    amount: { currency: 'USD', value: 1000 }
    }],
    total: {
    label: 'Total due',
    amount: { currency: tickets.currency, value : 1000 }
    }
    }
    const options = { !// requestPayerPhone, requestShipping, shippingType
    requestPayerEmail: true,
    requestPayerName: true,
    }

    View Slide

  77. Web payments api
    const request = new PaymentRequest(methods, details, options)
    PAYMENT REQUEST DEMO
    !// Add event listeners on user actions. Eg: shippingaddresschange
    paymentRequest.addEventListener(
    'paymentmethodchange', handlePaymentChange, false
    )
    paymentRequest.addEventListener(
    ‘shippingaddresschange', handleShippingAddressChange, false
    )
    request.show().then(response !=> {
    !// [process payment]
    !// Send to a Payment service provider (PWA), metrics, etc
    response.complete('success')
    }).catch((error) !=> {!/* Notify user on the error !*/})

    View Slide

  78. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    https://developers.google.com/web/fundamentals/payments/

    View Slide

  79. @JGFERREIRO
    @JGFERREIRO
    Local
    notifications
    9.

    View Slide

  80. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

  81. CACHE API :: HELLO WORLD
    export const launchNotification = ({artistId, isEnabled}) !=> {
    if ('Notification' in window) {
    Notification.requestPermission().then((permission) !=> {
    const artist = artists[artistId]
    const title = isEnabled
    ? `✅ Notifications for ${artist.name} are activated!`
    : `❌ Deactivate ${artist.name} notifications!`
    const options = {
    body: 'You will be notified for this event',
    icon: '/images/pennapps_logo_pwa_192_192.png',
    }
    })
    }
    }
    new Notification(title, options)

    View Slide

  82. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Advanced topics:
    Web Push Notifications: Timely, Relevant, and Precise
    Web Push Notifications through VAPID method

    View Slide

  83. @JGFERREIRO
    @JGFERREIRO
    App shell model
    10.

    View Slide

  84. @JGFERREIRO #PENNPWA
    The app "shell" is the minimal
    HTML, CSS and JavaScript
    required to power the user
    interface

    View Slide

  85. @JGFERREIRO
    @JGFERREIRO
    https://developers.google.com/web/fundamentals/architecture/app-shell

    View Slide

  86. @JGFERREIRO
    @JGFERREIRO #PENNPWA

    View Slide

  87. @JGFERREIRO - [email protected]
    Q&A!

    View Slide

  88. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    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 Slide

  89. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Action items
    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 Slide

  90. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    Research on advanced topics:
    1. Background sync
    2. IndexedDB
    3. Push notifications with Web Push
    4. HTTP2
    Action items (II)

    View Slide

  91. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    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 Slide

  92. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    One more thing…

    View Slide

  93. @JGFERREIRO
    @JGFERREIRO #PENNPWA
    ✅ T-shirt Eventbrite
    ✅ T-shirt "DevelopersInDepth" (DID)
    ✅ 1h pair programming session /
    coaching session with me
    ✅ Eventbrite stickers + DID stickers
    ✅ Badge "Best PWA in Pennapps"
    Pennapps PWA Contest
    bit.ly/pwa-contest

    View Slide

  94. @JGFERREIRO #PENNPWA
    PWA are the future of
    mobile apps. Start learning
    today

    View Slide

  95. Thanks #pennapps!
    @jgferreiro
    [email protected]

    View Slide