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

Once you go PRPL: SeattleJS

4e3a8581bae65a5a8d89dc5015aac185?s=47 Houssein Djirdeh
August 11, 2017
160

Once you go PRPL: SeattleJS

4e3a8581bae65a5a8d89dc5015aac185?s=128

Houssein Djirdeh

August 11, 2017
Tweet

Transcript

  1. XKCD/Installing

  2. Once you go PRPL… @hdjirdeh

  3. None
  4. None
  5. None
  6. CSS JS PNG

  7. <link rel="preload" as="script" href="script.js"> <link rel="preload" as="script" href="script.js"> <html lang="en">

    <head> <link rel="stylesheet" href="styles.css"> </head> <body> <!--(>'-')> <('-'<)--> <script src="script.js"></script> </body> </html>
  8. <link rel="preload" as="script" href="script.js">

  9. JS JS

  10. <link rel="preload" as="script" href="script.js"> as="script" <link rel="preload" as="style" href="styles.css"> as="style"

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

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

  13. <link rel="prefetch">

  14. preload-webpack-plugin <link rel="preload" href="chunk.cf7bd8260d685f704bd0.js" as="script"> <link rel="prefetch" href="chunk.cf7bd8260d685f704bd0.js">

  15. CAN I HAZ? Partial Support

  16. HTTP/2 Server Push

  17. None
  18. Link: </app/style.css>; rel=preload; as=style Link: </app/script.js>; rel=preload; as=script

  19. None
  20. Link: </app/style.css>; rel=preload; as=style; nopush Link: </app/script.js>; rel=preload; as=script

  21. A Comprehensive Guide To HTTP/2 Server Push - Jeremy Wagner

    https://rebrand.ly/http2
  22. Pushing too much Pushing unused assets Cache?

  23. PUSH critical resources

  24. None
  25. Service workers

  26. A service worker is a script that runs in the

    background of your browser when you view a webpage.
  27. ADDING A SERVICE WORKER 1. Create the file and write

    the logic yourself 2. Use a library
  28. None
  29. npm install workbox-cli --global workbox-cli generate:sw

  30. None
  31. <script> if ('serviceWorker' in navigator) { window.addEventListener('load', function () {

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

  34. APPLICATION SHELL CONTENT

  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'
  36. BUILD PROCESS

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

    "{build} && workbox-cli generate:sw" }
  38. workbox-webpack-plugin

  39. DYNAMIC CONTENT

  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
  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
  42. networkFirst

  43. networkFirst cacheFirst fastest cacheOnly networkOnly

  44. APP SHELL + DYNAMIC CACHING

  45. OFFLINE SUPPORT + FASTER REPEAT VISITS

  46. CAN I HAZ? Under development

  47. Service Worker H2 Push

  48. PRE-CACHE resources

  49. BUNDLES

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

  51. CODE SPLITTING

  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'
  53. import Loadable from 'react-loadable'; import Loading from './loading.component'; const LoadableComponent

    = Loadable({ loader: () => import('./details.component'), loading: Loading, });
  54. None
  55. WEBPACK BUNDLE ANALYZER

  56. bundlesize

  57. LAZY LOAD remaining routes

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

    LOAD remaining routes
  59. Native Progressive Web

  60. TIME TO INTERACTIVE

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

  63. @hdjirdeh