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

Progressive Web Apps in the Real World

Progressive Web Apps in the Real World

This workshop was first presented at Devoxx UK Conference on the 8th June 2016.

http://cfp.devoxx.co.uk/2016/speaker/dean_hume

Presentation Details
----------------------------------

As web developers, we are constantly striving to provide our users with the best possible browsing experience. Regardless of their device, our aim is to provide them with resilient, performant websites that just work. Imagine if you could take this to the next level and provide your users with a super fast website with a similar experience to native applications. This is where Service Workers come in.

They are a promising game changer that provides developers with powerful features such as offline browsing, periodic background syncs, and push notifications to name just a few!

This talk will dive into Progressive apps and showcase some of the features that are available for developers to start using today.

Topics include:
- The basics of Service Workers
- Eliminating third-party single points of failure
- Supercharging your caching
- Implement offline browsing
- Push notifications on the web
- Background Sync
- How to debug your Service Worker and much more!

In this talk, we will run through working a few working examples and explore the ins and outs of Progressive. This talk is aimed at all web developers regardless of skill level - there is something for everyone!

For more information visit http://deanhume.com

Dean Hume

June 08, 2016
Tweet

More Decks by Dean Hume

Other Decks in Technology

Transcript

  1. PROGRESSIVE
    WEB APPS
    in the real world

    View full-size slide

  2. Dean Hume
    @deanohume

    View full-size slide

  3. A Progressive Web App
    uses modern web
    capabilities to deliver an
    app-like user experience

    View full-size slide

  4. CORE DRIVERS

    View full-size slide

  5. CORE DRIVERS
    URLS & Links

    View full-size slide

  6. CORE DRIVERS
    URLS & Links System Capabilities

    View full-size slide

  7. CORE DRIVERS
    URLS & Links
    Accessible
    System Capabilities

    View full-size slide

  8. CORE DRIVERS
    URLS & Links
    Accessible
    System Capabilities
    Free!

    View full-size slide

  9. These apps aren’t packaged
    and deployed through stores,
    they’re just websites that took
    all the right vitamins.
    Alex Russell

    View full-size slide

  10. NO INSTALL NEEDED
    Awesome

    View full-size slide

  11. NO INSTALL NEEDED
    NO DOWNLOAD
    Awesome

    View full-size slide

  12. NO INSTALL NEEDED
    NO DOWNLOAD
    BUILT ON THE FABRIC OF THE WEB
    Awesome

    View full-size slide

  13. You are already using them

    View full-size slide

  14. What does this
    actually mean
    for our users?

    View full-size slide

  15. What does this
    actually mean
    for our users?
    ★ More engaging

    View full-size slide

  16. What does this
    actually mean
    for our users?
    ★ More engaging
    ★ Faster

    View full-size slide

  17. What does this
    actually mean
    for our users?
    ★ More engaging
    ★ Faster
    ★ Reliable

    View full-size slide

  18. This
    Talk
    1. Understanding Progressive Web Apps

    View full-size slide

  19. This
    Talk
    1. Understanding Progressive Web Apps
    2. Engage your users

    View full-size slide

  20. This
    Talk
    1. Understanding Progressive Web Apps
    2. Engage your users
    3. Speed up your site

    View full-size slide

  21. This
    Talk
    1. Understanding Progressive Web Apps
    2. Engage your users
    3. Speed up your site
    4. Improve reliability

    View full-size slide

  22. Understanding
    progressive web
    apps
    1

    View full-size slide

  23. Service
    workers

    View full-size slide

  24. Think of your web apps requests
    as planes taking off.
    ServiceWorker is the air traffic
    controller that routes the
    requests.
    Jeff Posnick

    View full-size slide

  25. “The perfect
    progressive
    enhancement.”

    View full-size slide

  26. Behind the scenes

    View full-size slide

  27. With Service Workers

    View full-size slide

  28. With Service Workers

    View full-size slide

  29. With Service Workers

    View full-size slide

  30. With Service Workers

    View full-size slide

  31. Service Workers are
    the key to unlocking
    the power

    View full-size slide

  32. The Approach

    View full-size slide

  33. The Approach
    App. Shell Architecture

    View full-size slide

  34. The Approach
    Pick & Choose
    App. Shell Architecture

    View full-size slide

  35. Application Shell Architecture

    View full-size slide

  36. bit.ly/app-shell

    View full-size slide

  37. Or pick & choose
    the features you
    like!

    View full-size slide

  38. operasoftware.github.io/pwa-list

    View full-size slide

  39. Summary
    ❖ Service Workers
    ❖ SSL only
    ❖ Architecture

    View full-size slide

  40. 2.Engage your users

    View full-size slide

  41. 2.1 Look and feel

    View full-size slide

  42. 2.1 Look and feel
    2.2 Push notifications

    View full-size slide

  43. 2.1 Look and feel
    2.3 Add to home screen
    2.2 Push notifications

    View full-size slide

  44. Look and feel

    View full-size slide

  45. Look and feel






    content="black-translucent">

    View full-size slide

  46. Look and feel
    bit.ly/color-custom

    View full-size slide

  47. Manifest
    A simple JSON file that
    allows you to control how
    your app appears to the
    user

    View full-size slide

  48. {
    lang: "en",
    background_color: "#09adec",
    name: "Building Great Startup Teams",
    short_name: "Building Great Startup Teams",
    display: "standalone",
    icons:
    [
    {
    src: "./images/logo-144.png",
    sizes: "144x144",
    type: "image/png"
    }
    ],
    start_url: "./index.html",
    orientation: "portrait"
    }

    View full-size slide

  49. {
    lang: "en",
    background_color: "#09adec",
    name: "Building Great Startup Teams",
    short_name: "Building Great Startup Teams",
    display: "standalone",
    icons:
    [
    {
    src: "./images/logo-144.png",
    sizes: "144x144",
    type: "image/png"
    }
    ],
    start_url: "./index.html",
    orientation: "portrait"
    }

    View full-size slide

  50. {
    lang: "en",
    background_color: "#09adec",
    name: "Building Great Startup Teams",
    short_name: "Building Great Startup Teams",
    display: "standalone",
    icons:
    [
    {
    src: "./images/logo-144.png",
    sizes: "144x144",
    type: "image/png"
    }
    ],
    start_url: "./index.html",
    orientation: "portrait"
    }

    View full-size slide

  51. Manifest
    bit.ly/manifest-json

    View full-size slide

  52. Manifest Generator
    tomitm.github.io/appmanifest

    View full-size slide

  53. Push
    Notifications

    View full-size slide

  54. Three Steps
    1. Subscribe User

    View full-size slide

  55. Three Steps
    1. Subscribe User
    2. Save Subscription

    View full-size slide

  56. Three Steps
    1. Subscribe User
    2. Save Subscription
    3. Send from Google Cloud

    View full-size slide

  57. Subscribe
    User

    View full-size slide

  58. if ('serviceWorker' in navigator) {
    }

    View full-size slide

  59. if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('service-worker.js').then(function
    (registration) {
    // Registration was successful
    }).catch(function(err) {
    // registration failed :(
    console.log('ServiceWorker registration failed: ', err);
    });
    }

    View full-size slide

  60. if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('service-worker.js').then(function
    (registration) {
    // Registration was successful
    registration.pushManager.subscribe({userVisibleOnly: true})
    .then(function(subscription){
    });
    }).catch(function(err) {
    // registration failed :(
    console.log('ServiceWorker registration failed: ', err);
    });
    }

    View full-size slide

  61. Save
    Subscription

    View full-size slide

  62. if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('service-worker.js').then(function
    (registration) {
    // Registration was successful
    registration.pushManager.subscribe({userVisibleOnly: true})
    .then(function(subscription){
    // Send to Server
    return sendSubscriptionToServer(subscription);
    });
    }).catch(function(err) {
    // registration failed :(
    console.log('ServiceWorker registration failed: ', err);
    });
    }

    View full-size slide

  63. Send
    from
    Google
    Cloud

    View full-size slide

  64. { "name": "Push Demo",
    "short_name": "Push Demo",
    "icons": [{ "src": "icon.png", "sizes": "192x192", "type": "image/png"
    }],
    "start_url": "/index.html",
    "display": "standalone",
    "gcm_sender_id": "57874135625436178",
    "gcm_user_visible_only": true,
    "permissions": [
    "gcm"
    ]}
    Manifest

    View full-size slide

  65. bit.ly/push-notifications-google
    bit.ly/push-notifications-dean
    Further reading

    View full-size slide

  66. https://deanhume.github.io/typography

    View full-size slide

  67. Add to home
    screen

    View full-size slide

  68. Add to
    home screen

    View full-size slide

  69. Add to home screen
    1. You need a manifest.json file

    View full-size slide

  70. Add to home screen
    1. You need a manifest.json file
    2. Your manifest file needs a start URL

    View full-size slide

  71. Add to home screen
    1. You need a manifest.json file
    2. Your manifest file needs a start URL
    3. You need a 144x144 PNG icon

    View full-size slide

  72. Add to home screen
    1. You need a manifest.json file
    2. Your manifest file needs a start URL
    3. You need a 144x144 PNG icon
    4. Your site is using a Service Worker
    running over HTTPS

    View full-size slide

  73. Add to home screen
    1. You need a manifest.json file
    2. Your manifest file needs a start URL
    3. You need a 144x144 PNG icon
    4. Your site is using a Service Worker
    running over HTTPS
    5. The user has visited your site at least
    twice, with at least five minutes
    between visits.

    View full-size slide

  74. {
    lang: "en",
    background_color: "#09adec",
    name: "Building Great Startup Teams",
    short_name: "Building Great Startup Teams",
    display: "standalone",
    icons:
    [
    {
    src: "./images/logo-144.png",
    sizes: "144x144",
    type: "image/png"
    }
    ],
    start_url: "./index.html",
    orientation: "portrait"
    }

    View full-size slide

  75. Look and feel
    Add to home screen
    Push notifications
    Sum
    m
    ary

    View full-size slide

  76. 3.Speed up your site

    View full-size slide

  77. 3.1 Caching
    3.2 Save-Data Header

    View full-size slide

  78. 3.1 Caching
    3.3 Background Sync
    3.2 Save-Data Header

    View full-size slide

  79. With Service Workers

    View full-size slide

  80. With Service Workers

    View full-size slide

  81. var cacheVersion = 1;
    var currentCache = { assetCache: 'cache' + cacheVersion };
    Caching

    View full-size slide

  82. var cacheVersion = 1;
    var currentCache = { assetCache: 'cache' + cacheVersion };
    this.addEventListener('install', event => {
    event.waitUntil(caches.open(currentCache.assetCache)
    .then(function(cache) {
    })
    );
    });
    Caching

    View full-size slide

  83. var cacheVersion = 1;
    var currentCache = { assetCache: 'cache' + cacheVersion };
    this.addEventListener('install', event => {
    event.waitUntil(caches.open(currentCache.assetCache)
    .then(function(cache) {
    return cache.addAll(['result.min.css', './js/material.min.js']);
    })
    );
    });
    Caching

    View full-size slide

  84. var cacheVersion = 1;
    var currentCache = { assetCache: 'cache' + cacheVersion };
    this.addEventListener('install', event => {
    event.waitUntil(caches.open(currentCache.assetCache)
    .then(function(cache) {
    return cache.addAll(['result.min.css', './js/material.min.js']);
    })
    );
    });
    this.addEventListener('fetch', event => {
    event.respondWith(caches.match(event.request)
    .then(function (response) {
    return response || fetch(event.request);
    })
    );
    });
    Caching

    View full-size slide

  85. github.com/GoogleChrome/sw-toolbox
    bit.ly/sw-toolbox

    View full-size slide

  86. Save-Data Header

    View full-size slide

  87. Using Service Workers

    View full-size slide

  88. Using Service Workers

    View full-size slide

  89. this.addEventListener('fetch', event => {
    if(event.request.headers.get('save-data')){
    if (/\.jpg$|.gif$|.png$/.test(event.request.url)) {
    // We can do something
    event.respondWith(
    fetch(‘low-quality-’ + event.request.url, {
    mode: 'no-cors'
    })
    }
    }
    });

    View full-size slide

  90. this.addEventListener('fetch', event => {
    if(event.request.headers.get('save-data')){
    if (/\.jpg$|.gif$|.png$/.test(event.request.url)) {
    // We can do something
    event.respondWith(
    fetch(‘low-quality-’ + event.request.url, {
    mode: 'no-cors'
    })
    }
    }
    });

    View full-size slide

  91. this.addEventListener('fetch', event => {
    if(event.request.headers.get('save-data')){
    if (/\.jpg$|.gif$|.png$/.test(event.request.url)) {
    // We can do something
    event.respondWith(
    fetch(‘low-quality-’ + event.request.url, {
    mode: 'no-cors'
    })
    }
    }
    });

    View full-size slide

  92. this.addEventListener('fetch', event => {
    if(event.request.headers.get('save-data')){
    if (/\.jpg$|.gif$|.png$/.test(event.request.url)) {
    // We can do something
    event.respondWith(
    fetch(‘low-quality-’ + event.request.url, {
    mode: 'no-cors'
    })
    }
    }
    });

    View full-size slide

  93. buildingstartupteams.com

    View full-size slide

  94. buildingstartupteams.com

    View full-size slide

  95. Saved 900 KB!

    View full-size slide

  96. Background sync

    View full-size slide

  97. Using Service Workers

    View full-size slide

  98. Using Service Workers

    View full-size slide

  99. With Service Workers

    View full-size slide

  100. Try later….

    View full-size slide

  101. // Request a one-off sync:
    navigator.serviceWorker.ready.then(
    function(swRegistration) {
    return swRegistration.sync.register('myFirstSync');
    });

    View full-size slide

  102. // Request a one-off sync:
    navigator.serviceWorker.ready.then(
    function(swRegistration) {
    return swRegistration.sync.register('myFirstSync');
    });
    self.addEventListener('sync', function(event) {
    if (event.tag == 'myFirstSync') {
    event.waitUntil(expensiveOperation());
    }
    });

    View full-size slide

  103. // Request a one-off sync:
    navigator.serviceWorker.ready.then(
    function(swRegistration) {
    return swRegistration.sync.register('myFirstSync');
    });
    self.addEventListener('sync', function(event) {
    if (event.tag == 'myFirstSync') {
    event.waitUntil(expensiveOperation());
    }
    });

    View full-size slide

  104. Background sync
    bit.ly/background-sync

    View full-size slide

  105. Caching
    Background Sync
    Save-Data Header
    Sum
    m
    ary

    View full-size slide

  106. 4.1 Offline Browsing
    4.2 3rd Party Scripts

    View full-size slide

  107. With Service Workers

    View full-size slide

  108. this.addEventListener('fetch', event => {
    };

    View full-size slide

  109. this.addEventListener('fetch', event => {
    // Check if the user navigated
    if (event.request.method === 'GET' && event.request.headers.
    get('accept').includes('text/html')) {
    // Respond appropriately
    }
    };

    View full-size slide

  110. this.addEventListener('fetch', event => {
    // Check if the user navigated
    if (event.request.method === 'GET' && event.request.headers.
    get('accept').includes('text/html')) {
    // Respond appropriately
    event.respondWith(
    fetch(event.request.url).catch(error => {
    // Return the offline page
    return caches.match('the-offline-page');
    }));
    }
    };

    View full-size slide

  111. Offline Applications
    bit.ly/offline-apps
    bit.ly/offline-page

    View full-size slide

  112. 3rd Party Scripts

    View full-size slide

  113. Server Fails

    View full-size slide

  114. Using Service Workers

    View full-size slide

  115. Using Service Workers

    View full-size slide

  116. With Service Workers

    View full-size slide

  117. function timeout(delay) {
    return new Promise(function(resolve, reject) {
    setTimeout(function(){
    resolve(new Response('', { status: 408, statusText:
    'Request timed out.' }));
    }, delay);
    });
    }

    View full-size slide

  118. function timeout(delay) {
    return new Promise(function(resolve, reject) {
    setTimeout(function(){
    resolve(new Response('', { status: 408, statusText:
    'Request timed out.' }));
    }, delay);
    });
    }
    self.addEventListener('fetch', event => {
    });

    View full-size slide

  119. function timeout(delay) {
    return new Promise(function(resolve, reject) {
    setTimeout(function(){
    resolve(new Response('', { status: 408, statusText:
    'Request timed out.' }));
    }, delay);
    });
    }
    self.addEventListener('fetch', event => {
    event.respondWith(Promise.race([timeout(6000), fetch
    (event.request.url)]));
    });

    View full-size slide

  120. bit.ly/sw-timeout

    View full-size slide

  121. Summary
    1. Understanding Progressive Web Apps
    2. Engage your users
    3. Speed up your site
    4. Improve reliability

    View full-size slide

  122. Performance
    is a feature

    View full-size slide

  123. Further reading
    ❖ Shell Architecture - bit.ly/instant-shell
    ❖ Getting Started - bit.ly/starting-pwas
    ❖ Service Worker - bit.ly/pwa-swers
    ❖ Code Labs -bit.ly/code-labs-pwa
    ❖ Recipes
    ➢ bit.ly/mozilla-service-workers
    ➢ bit.ly/chrome-service-workers

    View full-size slide

  124. What’s still to come?

    View full-size slide

  125. What’s still to come?
    Web Bluetooth
    webbluetoothcg.github.io/web-bluetooth
    Streams API
    jakearchibald.com/2016/streams-ftw
    Web NFC
    w3c.github.io/web-nfc
    Geofencing
    w3c.github.io/geofencing-api

    View full-size slide

  126. Thank you!
    @
    deanohum
    e

    View full-size slide