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

Once you go PRPL: SeattleJS

Houssein Djirdeh
August 11, 2017
170

Once you go PRPL: SeattleJS

Houssein Djirdeh

August 11, 2017
Tweet

Transcript

  1. XKCD/Installing

    View Slide

  2. Once you go PRPL…
    @hdjirdeh

    View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. CSS
    JS
    PNG

    View Slide












  7. View Slide


  8. View Slide

  9. JS
    JS

    View Slide


  10. as="script"

    as="style"
    as="font"
    as="audio"
    as="image"
    as="video"

    View Slide

  11. as="script"
    as="style"

    View Slide

  12. as="script"
    as="style"
    as="font"
    as="audio"
    as="image"
    as="video"

    View Slide


  13. View Slide

  14. preload-webpack-plugin


    View Slide

  15. CAN I HAZ?
    Partial Support

    View Slide

  16. HTTP/2 Server Push

    View Slide

  17. View Slide

  18. Link: ; rel=preload; as=style
    Link: ; rel=preload; as=script

    View Slide

  19. View Slide

  20. Link: ; rel=preload; as=style; nopush
    Link: ; rel=preload; as=script

    View Slide

  21. A Comprehensive Guide To HTTP/2 Server Push - Jeremy Wagner
    https://rebrand.ly/http2

    View Slide

  22. Pushing too much
    Pushing unused assets
    Cache?

    View Slide

  23. PUSH critical resources

    View Slide

  24. View Slide

  25. Service workers

    View Slide

  26. A service worker is a script that runs
    in the background of your browser when
    you view a webpage.

    View Slide

  27. ADDING A SERVICE WORKER
    1. Create the file and write the logic yourself
    2. Use a library

    View Slide

  28. View Slide

  29. npm install workbox-cli --global
    workbox-cli generate:sw

    View Slide

  30. View Slide

  31. <br/>if ('serviceWorker' in navigator) {<br/>window.addEventListener('load', function () {<br/>navigator.serviceWorker.register('/service-worker.js').then(function(){<br/>// Registration was successful<br/>console.log('ServiceWorker registration successful!');<br/>}).catch(function(err) {<br/>// registration failed :(<br/>console.log('ServiceWorker registration failed: ', err);<br/>});<br/>});<br/>}<br/>
    if ('serviceWorker' in navigator) {
    window.addEventListener('load', function () {
    navigator.serviceWorker.register('/service-worker.js')
    <br/>if ('serviceWorker' in navigator) {<br/>window.addEventListener('load', function () {<br/>navigator.serviceWorker.register('/service-worker.js').then(function(){<br/>// Registration was successful<br/>console.log('ServiceWorker registration successful!');<br/>}).catch(function(err) {<br/>// registration failed :(<br/>console.log('ServiceWorker registration failed: ', err);<br/>});<br/>});<br/>}<br/>
    <br/>if ('serviceWorker' in navigator) {<br/>window.addEventListener('load', function () {<br/>navigator.serviceWorker.register('/service-worker.js').then(function(){<br/>// Registration was successful<br/>console.log('ServiceWorker registration successful!');<br/>}).catch(function(err) {<br/>// registration failed :(<br/>console.log('ServiceWorker registration failed: ', err);<br/>});<br/>});<br/>}<br/>

    View Slide

  32. View Slide

  33. APPLICATION SHELL

    View Slide

  34. APPLICATION SHELL CONTENT

    View Slide

  35. module.exports = {
    globDirectory: 'dist/',
    globPatterns: ['**/*.{js,png,svg,html,json}'],
    swDest: 'dist/service-worker.js',
    navigateFallback: '/index.html'
    };
    module.exports = {
    globDirectory: 'dist/',
    globPatterns: ['**/*.{js,png,svg,html,json}'],
    swDest: 'dist/service-worker.js',
    navigateFallback: '/index.html',
    };
    module.exports = {
    globDirectory: 'dist/',
    globPatterns: ['**/*.{js,png,svg,html,json}'],
    swDest: 'dist/service-worker.js',
    navigateFallback: '/index.html'
    };
    globDirectory: 'dist/'
    globPatterns: ['**/*.{js,png,svg,html,json}']
    swDest: 'dist/service-worker.js'
    navigateFallback: '/index.html'

    View Slide

  36. BUILD PROCESS

    View Slide

  37. npm install workbox-cli --save-dev
    // package.json
    "scripts": {
    //...
    "build": "{build} && workbox-cli generate:sw"
    }

    View Slide

  38. workbox-webpack-plugin

    View Slide

  39. DYNAMIC CONTENT

    View Slide

  40. module.exports = {
    globDirectory: 'dist/',
    globPatterns: ['**/*.{js,png,svg,html,json}'],
    swDest: 'dist/service-worker.js',
    navigateFallback: '/index.html',
    runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    };
    module.exports = {
    globDirectory: 'dist/',
    globPatterns: ['**/*.{js,png,svg,html,json}'],
    swDest: 'dist/service-worker.js',
    navigateFallback: '/index.html',
    runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    };
    runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    networkFirst

    View Slide

  41. runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    module.exports = {
    globDirectory: 'dist/',
    globPatterns: ['**/*.{js,png,svg,html,json}'],
    swDest: 'dist/service-worker.js',
    navigateFallback: '/index.html',
    runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    };
    runtimeCaching: [
    {
    urlPattern: /^https:\/\/your.api.com\/.*/,
    handler: 'networkFirst'
    }
    ]
    networkFirst

    View Slide

  42. networkFirst

    View Slide

  43. networkFirst
    cacheFirst
    fastest
    cacheOnly
    networkOnly

    View Slide

  44. APP SHELL
    +
    DYNAMIC CACHING

    View Slide

  45. OFFLINE SUPPORT
    +
    FASTER REPEAT VISITS

    View Slide

  46. CAN I HAZ?
    Under development

    View Slide

  47. Service Worker
    H2 Push

    View Slide

  48. PRE-CACHE resources

    View Slide

  49. BUNDLES

    View Slide

  50. 4KB - 145KB
    Size of JS frameworks, gzipped
    Restuta/framework-sizes.md GIST

    View Slide

  51. CODE SPLITTING

    View Slide

  52. export const routes: Routes = [
    { path: '', redirectTo: 'main', pathMatch: 'full' },
    { path: 'main', component: MainComponent },
    { path: 'details', loadChildren: 'details/details.module#DetailsModule' }
    ];
    export const routes: Routes = [
    { path: '', redirectTo: 'main', pathMatch: 'full' },
    { path: 'main', component: MainComponent },
    { path: 'details', loadChildren: 'details/details.module#DetailsModule' }
    ];
    loadChildren: 'details/details.module#DetailsModule'

    View Slide

  53. import Loadable from 'react-loadable';
    import Loading from './loading.component';
    const LoadableComponent = Loadable({
    loader: () => import('./details.component'),
    loading: Loading,
    });

    View Slide

  54. View Slide

  55. WEBPACK BUNDLE ANALYZER

    View Slide

  56. bundlesize

    View Slide

  57. LAZY LOAD remaining routes

    View Slide

  58. PRPL
    PUSH critical resources
    RENDER initial route
    PRE-CACHE resources
    LAZY LOAD remaining routes

    View Slide

  59. Native
    Progressive Web

    View Slide

  60. TIME TO INTERACTIVE

    View Slide

  61. View Slide

  62. ADDITIONAL
    developers.google.com/web/tools/lighthouse
    Lighthouse
    webpagetest.org/easy
    WebPageTest
    ebidel/lighthouse-ci
    hnpwa.com
    HNPWA

    View Slide

  63. @hdjirdeh

    View Slide