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

LDNWebPerf November 2016 - Peter O’Shaughnessy

LDNWebPerf November 2016 - Peter O’Shaughnessy

Developing a progressive web app for Snapchat-like selfies has led me to learn about service worker practicalities, client-side image generation and standalone app limitations. I've come unstuck by a Chromium bug and sparked a WICG discussion. Combining the things I've learned along the way with advice I've received from Google…

London Web Performance Group

November 01, 2016
Tweet

More Decks by London Web Performance Group

Other Decks in Technology

Transcript

  1. Peter O'Shaughnessy
    @poshaughnessy
    @samsunginternet
    Progressive Web Apps
    Service Workers & Server-free Selfies !

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. Snapchat by Snap Inc.
    Not to be confused with... "

    View Slide

  7. “PWAs combine the best of web & the best of
    native”
    #

    View Slide

  8. Multi-platform
    Frictionless
    Discoverable
    Accessible
    Best of web $

    View Slide

  9. Add to Home Screen
    Offline
    Instant load
    Push notifications
    Best of native %

    View Slide

  10. “PWAs are all about removing friction”
    &

    View Slide

  11. Service Workers '

    View Slide

  12. var RESOURCES = ['/images/emojione/1f600.svg', ...];
    self.addEventListener('install', function(event) {
    function onInstall () {
    return caches.open(CACHE_NAME)
    .then(function(cache) {
    return cache.addAll(RESOURCES);
    });
    }
    );
    ( Don't cache too much on install! ⚖

    View Slide

  13. View Slide

  14. Emoji One SVGs (left), Unicode emojis (right)

    View Slide

  15. gulp.task('generate-service-worker', function(callback) {
    swPrecache.write(path.join(rootDir, 'service-worker.js'), {
    staticFileGlobs: [rootDir + '/**/*.{js,html,css,svg}'],
    stripPrefix: rootDir
    }, callback);
    });
    github.com/GoogleChrome/sw-precache
    * Automate precache resource list +

    View Slide

  16. // sw.js
    import resources from '\0initial-resources';
    ...
    cache.addAll( resources );
    bit.ly/rollup-precache

    View Slide

  17. const RESOURCES = [
    '/',
    '/index.html',
    ...
    ];
    ...
    cache.addAll( RESOURCES );
    , URLs, not files -

    View Slide

  18. . Remember to check Lighthouse /0

    View Slide

  19. 1. SSR app shell & initial page. CSR takes over.
    2. SSR only app shell. JS fetches rest on load.
    3. SSR full page.
    4. CSR full page.
    5 Rendering preferences (in order) 1

    View Slide

  20. “cache first”, then fallback to network
    toolbox.router.get('/images', toolbox.cacheFirst);
    6 Easy caching strategies with sw-toolbox
    2

    View Slide

  21. “network first”, then fallback to cache
    toolbox.router.get('/api', toolbox.networkFirst);

    View Slide

  22. “fastest” — serve whichever comes back first
    toolbox.router.get('/profile', toolbox.fastest);
    “network only”
    “cache only”

    View Slide

  23. getUserMedia 3

    View Slide

  24. ( Enhance progressively! 4

    View Slide

  25. * Standalone & localhost: prompt doesn't
    appear 5

    View Slide

  26. const constraints = {
    width: {ideal: width, max: width},
    height: {ideal: height, max: height}
    };
    navigator.mediaDevices.getUserMedia({video: constraints})
    ...
    , Don't rely on getUserMedia constraints 6

    View Slide

  27. Saving images 7

    View Slide

  28. var link = document.createElement('a');
    link.download = 'My Snapwat';
    link.href = dataURI;
    link.click();
    ( Common hack ⛏

    View Slide

  29. * Data-uri downloads currently blocked ⛔

    View Slide

  30. , requests bypass SW :

    View Slide

  31. window.open(canvas.toDataURL('image/png'), '_blank');
    4 'New tab' in standalone mode kills page ;

    View Slide

  32. 5 No long tap menu in standalone mode <

    View Slide

  33. = Save image disabled if image too big >

    View Slide

  34. bit.ly/save-image-feature
    Do we need a 'save image' feature? ?

    View Slide

  35. orientation (I used JavaScript-Load-
    Image)
    Calculating canvas text bounds
    Text doesn't render when over ~240px?
    Other tricky things @

    View Slide

  36. Next for Snapwat? ⏩

    View Slide

  37. Push notifications B

    View Slide

  38. Web Share API C

    View Slide

  39. Head tracking D

    View Slide

  40. Brushes E
    Undo/Redo ↩↪
    Local storage? H
    Any suggestions...? I

    View Slide

  41. Next for PWAs? J

    View Slide

  42. Service worker & cache API improvements K

    View Slide

  43. navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('syncTest');
    }).then(function() {
    log('Sync registered');
    });
    Background sync ⛰

    View Slide

  44. Link: ; rel="serviceworker"
    Origin-Trial: token_obtained_from_signup
    bit.ly/foreign-fetch
    Foreign fetch ✈

    View Slide

  45. jakearchibald.com/2016/service-worker-meeting-notes/
    Multiple service workers for parallelisation?
    N

    View Slide

  46. self.addEventListener('fetch', function(event) {
    if (event.request.headers.get('save-data')) {
    ...
    bit.ly/save-data-header
    Save-Data header O

    View Slide

  47. P snapw.at
    Q github.com/SamsungInternet/snapwat

    View Slide

  48. @poshaughnessy
    @samsunginternet
    github.com/samsunginternet
    medium.com/samsung-internet-dev
    Thanks! R

    View Slide