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

Progressive Web Apps - fullStackTO/FITC Web Unleashed

4e3a8581bae65a5a8d89dc5015aac185?s=47 Houssein Djirdeh
September 26, 2017
200

Progressive Web Apps - fullStackTO/FITC Web Unleashed

4e3a8581bae65a5a8d89dc5015aac185?s=128

Houssein Djirdeh

September 26, 2017
Tweet

Transcript

  1. PROGRESSIVE WEB APPLICATIONS @hdjirdeh

  2. None
  3. None
  4. WEBPAGE INGREDIENT INGREDIENT INGREDIENT INGREDIENT INGREDIENT INGREDIENT

  5. PWAs use modern web capabilities to provide a reliable, engaging

    and fast user experience on any device reliable engaging fast on any device
  6. None
  7. None
  8. NETWORK CONNECTION IS SECURE

  9. None
  10. CAN WORK WITH POOR/NO CONNECTION

  11. DOWNASAUR

  12. Service workers

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

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

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

  17. None
  18. <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>
  19. None
  20. APPLICATION SHELL

  21. APPLICATION SHELL CONTENT

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

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

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

  26. DYNAMIC CONTENT

  27. 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
  28. networkFirst cacheFirst fastest cacheOnly networkOnly

  29. APP SHELL + DYNAMIC CACHING

  30. OFFLINE SUPPORT + FASTER REPEAT VISITS

  31. None
  32. preview.starbucks.com

  33. CAN I HAZ? Under development

  34. PAGE LOAD IS FAST

  35. None
  36. CSS JS PNG

  37. <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>
  38. JS JS

  39. <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"
  40. <link rel="prefetch">

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

  42. CAN I HAZ? Partial Support

  43. HTTP/2 Server Push

  44. None
  45. None
  46. Link: </app/style.css>; rel=preload; as=style Link: </app/script.js>; rel=preload; as=script

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

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

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

  51. Service Worker H2 Push

  52. BUNDLES

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

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

  59. bundlesize

  60. FIRST MEANINGFUL PAINT TIME TO INTERACTIVE

  61. SHOW SOME CONTENT WITHOUT JAVASCRIPT

  62. <noscript> Sorry, JavaScript needs to be enabled in order to

    run this application. </noscript>
  63. SERVER SIDE RENDERING

  64. INSTALL ON YOUR DEVICE

  65. <link rel="manifest" href="/manifest.json">

  66. { name: "Angular 2 HN", short_name: "Angular 2 HN", icons:

    [ { src: "assets/icons/android-chrome-192x192.png", sizes: "192x192", type: "image/png" }, // ... ], theme_color: "#b92b27", background_color: "#ffffff", display: "standalone", orientation: "portrait" }
  67. APP INSTALL BANNER

  68. INSTALL TO HOMESCREEN

  69. SPLASH SCREEN

  70. APP LOADED

  71. CAN I HAZ? Under development

  72. SAFARI ON IOS Can install to homescreen but that’s it…

  73. <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="apple-touch-icon" sizes="180x180" href="icon.png">

    <link rel="apple-touch-icon" sizes="120x120" href="icon-120x120.png"> <link rel="apple-touch-icon" sizes="152x152" href="icon-152x152.png"> <link rel="apple-touch-icon" sizes="180x180" href="icon-180x180.png"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="apple-touch-icon" sizes="180x180" href="icon.png"> <link rel="apple-touch-icon" sizes="120x120" href="icon-120x120.png"> <link rel="apple-touch-icon" sizes="152x152" href="icon-152x152.png"> <link rel="apple-touch-icon" sizes="180x180" href="icon-180x180.png">
  74. None
  75. None
  76. Native Progressive Web

  77. Progressive web apps can replace native apps

  78. @hdjirdeh