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

Once you go PRPL - FullStackFest

4e3a8581bae65a5a8d89dc5015aac185?s=47 Houssein Djirdeh
September 07, 2017
23

Once you go PRPL - FullStackFest

4e3a8581bae65a5a8d89dc5015aac185?s=128

Houssein Djirdeh

September 07, 2017
Tweet

Transcript

  1. XKCD/Installing

  2. Once you go PRPL… @hdjirdeh

  3. PUSH critical resources RENDER initial route PRE-CACHE resources LAZY LOAD

    remaining routes P R L P
  4. None
  5. None
  6. None
  7. None
  8. CSS

  9. JS

  10. PNG

  11. <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>
  12. JS JS

  13. <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"
  14. <link rel="prefetch">

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

  16. CAN I HAZ? Partial Support

  17. HTTP/2 Server Push

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

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

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

    https://rebrand.ly/http2
  24. Pushing too much

  25. Pushing unused assets

  26. Cache?

  27. PUSH critical resources

  28. None
  29. Service workers

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

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

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

  34. None
  35. <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>
  36. None
  37. APPLICATION SHELL

  38. APPLICATION SHELL CONTENT

  39. 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'
  40. npm install workbox-cli --save-dev // package.json "scripts": { //... "build":

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

  42. DYNAMIC CONTENT

  43. 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' } ] 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' } ] }; networkFirst cacheFirst fastest cacheOnly networkOnly runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ]
  44. 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
  45. networkFirst

  46. networkFirst cacheFirst fastest cacheOnly networkOnly

  47. APP SHELL + DYNAMIC CACHING

  48. OFFLINE SUPPORT + FASTER REPEAT VISITS

  49. CAN I HAZ? Under development

  50. Service Worker H2 Push

  51. PRE-CACHE resources

  52. BUNDLES

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

  54. CODE SPLITTING

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

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

  60. bundlesize

  61. LAZY LOAD remaining routes

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

    LOAD remaining routes
  63. TIME TO INTERACTIVE FIRST PAINT

  64. None
  65. @hdjirdeh