ITOGO_Conf_-_Optimiser_les_performances_d_une_webapp.pdf

 ITOGO_Conf_-_Optimiser_les_performances_d_une_webapp.pdf

Dans cette présentation je décris la marche à suivre pour optimiser vos sites web ou vos applications web

D3bcad37b1ec0fc8ecdeb199e54a61e4?s=128

Dev-Mind

June 11, 2018
Tweet

Transcript

  1. 1.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Optimiser les performances d’une webapp
  2. 2.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Pourquoi une webapp doit être performante ?
  3. 6.

    #WebPerformance / 9 juin 2018 @guillaumeehret > 3 sec sur

    mobile ⇒ 57% des users en moins 0 : 03 DoubleClick, “The Need for Mobile Speed”, September 2016 https://giphy.com
  4. 10.

    #WebPerformance / 9 juin 2018 @guillaumeehret 2010 2017 2016 2015

    2014 2013 2012 2011 http://httparchive.org mars 2017 Taille moyenne des ressources d’un site web
  5. 14.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Mb en 2017

    Wifi 30Mb/s ⇒ 0.5 sec 4G 4Mb/s ⇒ 5 sec H+ 1.5Mb/s ⇒ 10 sec 3G 750kb/s ⇒ 25 sec Webpagetest.org, , February 2016
  6. 15.

    #WebPerformance / 9 juin 2018 @guillaumeehret Webpagetest.org, , February 2016

    Temps mobile 10s 3/4 19s moy 200 moy Les performances sur mobile ne sont pas toujours au rendez vous
  7. 20.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Que faire pour créer des webapps performantes ?
  8. 22.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 https://www.dev-mind.fr Développement Formations
  9. 23.

    #WebPerformance / 9 juin 2018 @guillaumeehret avec des crêpes et

    du coeur 19 et 20 avril 2018 à Lyon https://mixitconf.org/
  10. 24.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  11. 25.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  12. 31.

    #WebPerformance / 9 juin 2018 @guillaumeehret loadtime https://monsite/ HTML parsing

    parsing compile render JavaScript Autres CSS render JavaScript Autres CSS ... 1
  13. 32.

    #WebPerformance / 9 juin 2018 @guillaumeehret first paint JavaScript Autres

    JavaScript Autres ... 1 HTML https://monsite/ HTML parsing parsing compile render JavaScript Autres CSS render JavaScript Autres CSS ...
  14. 36.

    #WebPerformance / 9 juin 2018 @guillaumeehret Mes outils pour mesurer

    Webpagetest >> Pagespeed Insight >> Browser developper tools (Lighthouse) ... 1
  15. 44.

    #WebPerformance / 9 juin 2018 @guillaumeehret Avant de commencer 2

    7.4s first paint 18.2s loadtime Sans optim 1.6Mb size
  16. 45.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  17. 47.

    #WebPerformance / 9 juin 2018 @guillaumeehret <html> <head> <script .../>

    <body> <script .../> </body </html> JavaScript HTML 2
  18. 50.

    #WebPerformance / 9 juin 2018 @guillaumeehret Ordre de définition des

    scripts JS 2 7.4s first paint 18.2s loadtime Sans optim 1.6Mb size 6.4s first paint 18.2s loadtime 1.6Mb size -13.5% first paint 0% loadtime 0% size
  19. 54.

    #WebPerformance / 9 juin 2018 @guillaumeehret 2 HTTP2 et Java

    1. Container compatible Jetty 9.2, Undertow (JBoss) 1.3, Tomcat > 8.5 2. Activer le mode HTTP 2 3. Avoir un certificat 4. Ajouter le jar ALPN au jdk (lib pour Jdk < 9)
  20. 55.

    #WebPerformance / 9 juin 2018 @guillaumeehret HTTP 2 2 6.4s

    first paint 18.2s loadtime Ordre JS 1.6Mb size 6.4s first paint 18.1s loadtime 1.6Mb size 0% first paint -0.5% loadtime 0% size
  21. 56.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  22. 59.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Minification ressources txt

    JavaScript HTML sur mon exemple -22% -51% -26% CSS
  23. 61.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 public class SessionDto

    { public String title; public String summary; public String lang; public String format; public String description; public Instant start; public Instant room; ... } des DTO qui collent à l’API
  24. 62.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 public class SessionDto

    { public String title; public String summary; public String lang; public String format; public String description; public Instant start; public Instant room; ... } public class SessionListDto { public String title; public String summary; ... } des DTO qui collent à l’API
  25. 64.

    #WebPerformance / 9 juin 2018 @guillaumeehret Minification du texte 6.4s

    first paint 18.1s loadtime HTTP2 1.6Mb size 5.5s first paint 15.4s loadtime 1.3Mb size -14% first paint -15% loadtime -19% size 3
  26. 65.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Le texte se

    compresse CSS JavaScript HTML JSON les navigateurs acceptent le gzip
  27. 66.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Le texte se

    compresse JavaScript HTML JSON server: compression: enabled: true mime-types: application/json,text/html,text/css,application/javascript min-response-size: 2048 CSS
  28. 67.

    #WebPerformance / 9 juin 2018 @guillaumeehret Compression du texte 5.5s

    first paint 15.4s loadtime Minification 1.3Mb size 1.5s first paint 10.8s loadtime 940Kb size -72% first paint -30% loadtime -28% size 3
  29. 72.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Material Design Lite

    185kb 228kb 203kb 20kb Les frameworks CSS CSS CSS +JS CSS +JS CSS +JS CSS JS JS JQuery 69kb JQuery 69kb
  30. 73.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Quelques astuces Modularité

    frameworks Apprenez CSS CSS is awesome de Igor Laborie Nettoyage automatique avec uncss CSS
  31. 74.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 UnCSS return gulp.src(`${paths.main}/**/*.css`)

    .pipe($.if('*.css', $.uncss({ html : [ `${paths.main}/*.html`, `${paths.main}/component/**/*.html`, `${paths.main}/component/**/*.js`] }))) .pipe(gulp.dest(`${paths.dist}/styles`)); CSS
  32. 75.

    #WebPerformance / 9 juin 2018 @guillaumeehret Utilisation UnCSS 1.5s first

    paint 10.8s loadtime Compression 940Kb size 0.5s first paint 10.4s loadtime 920Kb size -67% first paint -3.7% loadtime -2.1% size 3 CSS
  33. 77.

    #WebPerformance / 9 juin 2018 @guillaumeehret Compression imagemin 0.5s first

    paint 10.4s loadtime UnCss 920Kb size 0.5s first paint 8.5s loadtime 735Kb size 0% first paint -18% loadtime -20% size 3 Images
  34. 78.

    #WebPerformance / 9 juin 2018 @guillaumeehret Transparence Couleurs Compression Animation

    Use case GIF 256 sans perte animation PNG au choix sans perte fond transp. PNG 8 bit 256 sans perte couleur limité JPEG toutes au choix photos SVG toutes sans perte indirectement logo, diag Les formats classiques 3 Images
  35. 80.
  36. 82.

    #WebPerformance / 9 juin 2018 @guillaumeehret webp expérimentation jpeg 2000

    jpeg_xr BPG Utilisez un format alternatif 3 Images
  37. 83.

    #WebPerformance / 9 juin 2018 @guillaumeehret <picture> la balise perdue

    3 Des images responsives en HTML avec la balise <picture> et la propriété srcset Images
  38. 85.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 <picture> <source srcset="img/mixit/mixit-amphi_640.webp

    640w, img/mixit/mixit-amphi_1024.webp 1024w, img/mixit/mixit-amphi_2048.webp" type="image/webp"/> <source srcset="img/mixit/mixit-amphi_640.jpg 640w, img/mixit/mixit-amphi_1024.jpg 1024w, img/mixit/mixit-amphi_2048.jpg"/> <img src="img/mixit/mixit-amphi_640.jpg" alt="Mix-IT amphi"> </picture> Images
  39. 86.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 <picture> <source srcset="img/mixit/mixit-amphi_640.webp

    640w, img/mixit/mixit-amphi_1024.webp 1024w, img/mixit/mixit-amphi_2048.webp" type="image/webp"/> <source srcset="img/mixit/mixit-amphi_640.jpg 640w, img/mixit/mixit-amphi_1024.jpg 1024w, img/mixit/mixit-amphi_2048.jpg"/> <img src="img/mixit/mixit-amphi_640.jpg" alt="Mix-IT amphi"> </picture> Images
  40. 87.

    #WebPerformance / 9 juin 2018 @guillaumeehret propriété srcset 3 <img

    src="img/mixit/mixit-amphi_640.jpg" srcset="img/mixit/mixit-amphi_640.jpg 640w, img/mixit/mixit-amphi_1024.jpg 1024w, img/mixit/mixit-amphi_2048.jpg"> la largeur de la fenêtre nombre entier suivi par 'w' (640w), par défaut c’est l’infini la densité de pixel nombre entier suivi par 'x' (2x), par défaut c’est 1x. Images
  41. 89.

    #WebPerformance / 9 juin 2018 @guillaumeehret image optimisation 3 0.5s

    first paint 8.5s loadtime imagemin 735Kb size 0.5s first paint 6.7s loadtime 572Kb size 0% first paint -21% loadtime -22% size Images
  42. 91.
  43. 92.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 Fonts Format Extension

    Exemple Font Roboto Compression EOT .eot 179 ko TrueType .ttf 179 ko WOFF .woff 89 ko >10 WOFF2 .woff2 64ko 30% + que WOFF >10 >10 SVG .svg 743 ko IE Edge Firefox Chrome Safari Opera Opera Mini Android Browser iOS Safari Chrome for Android
  44. 93.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 @font-face { font-family:

    Roboto; src: local('Roboto'), url(../fonts/Roboto-Regular.woff2) format('woff2'), url(../fonts/Roboto-Regular.woff) format('woff'), url(../fonts/Roboto-Regular.eot), url(../fonts/Roboto-Regular.ttf) format('truetype'), url(../fonts/Roboto-Regular.svg#Roboto) format('svg'); font-weight: 300; font-style: normal } body { font-family: Roboto, Arial, sans-serif; } Fonts
  45. 95.

    #WebPerformance / 9 juin 2018 @guillaumeehret CDN pour les fonts

    3 0.5s first paint 6.7s loadtime webp 572Kb size 440ms first paint 3.4s loadtime 231Kb size -12% first paint -49% loadtime -59% size
  46. 97.

    #WebPerformance / 9 juin 2018 @guillaumeehret Novembre 2010 Taille moyenne

    113 Ko moy 420 Ko JS moy JS Novembre 2016 3 JavaScript medium article Osmany, 2017
  47. 98.

    #WebPerformance / 9 juin 2018 @guillaumeehret 3 JavaScript JS Téléchargemen

    t Parsing 05 3C FE BA 44 C1 Génération bytecode Optimisation Compilation Exécution Pas que le chargement
  48. 99.

    #WebPerformance / 9 juin 2018 @guillaumeehret medium article Osmany, 2017

    Evaluation et parsing d’un script JavaScript de 1Mo 3 JavaScript
  49. 102.

    #WebPerformance / 9 juin 2018 @guillaumeehret Tree shaking 3 JavaScript

    import {a} from './module'; } console.log(a); module.js export function a() { return 'used'; } export function b() { return 'unused'; }
  50. 104.

    #WebPerformance / 9 juin 2018 @guillaumeehret import('./module').then( module => {...}

    ).catch( error => {...} ); Dynamic import 3 JavaScript https://github.com/tc39/proposal-dynamic-import est passé au dernier stade avant adoption
  51. 107.

    #WebPerformance / 9 juin 2018 @guillaumeehret Polyfill sur CDN 3

    <script src="https://cdn.polyfill.io/v2/polyfill.min.js"> </script> Size (min) 1370 8212 464 26430 6652 Size (min+gz) 514 2435 285 8497 2018 JavaScript
  52. 108.

    #WebPerformance / 9 juin 2018 @guillaumeehret CDN JS 3 440ms

    first paint 3.4s loadtime CDN font 231Kb size 440ms first paint 2.9s loadtime 200Kb size 0% first paint -15% loadtime -13% size JavaScript
  53. 109.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  54. 110.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 La ressource la plus rapide et la mieux optimisée est une ressource qui n'est pas envoyée. 4
  55. 112.

    #WebPerformance / 9 juin 2018 @guillaumeehret Cache serveur Cloud base

    de données ou I/O Temps fluctuant Abtraction Spring @Cacheable 4
  56. 121.

    #WebPerformance / 9 juin 2018 @guillaumeehret 4 Cache busting Versionner

    vos fichiers de ressources Pour le HTML limitez le max-age
  57. 122.

    #WebPerformance / 9 juin 2018 @guillaumeehret Refresh / Cache 440ms

    first paint 2.9s loadtime First load 200Kb size 427ms first paint 700ms loadtime 18Kb size -3% first paint -75% loadtime -91% size 4
  58. 123.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  59. 129.

    #WebPerformance / 9 juin 2018 @guillaumeehret 4 5 var worker

    = new Worker('doWork.js'); worker.addEventListener('message', (e) => { console.log('Worker said: ', e.data); }, false); worker.postMessage('Hello World'); self.addEventListener('message',(e) => { self.postMessage(e.data); }, false); doWork.js
  60. 132.

    #WebPerformance / 9 juin 2018 @guillaumeehret Service worker 5 sw-precache

    module node générant la configuration sw-toolbox lib JS qui fournit des utilitaires pour gérer le cache avec différentes stratégies : networkFirst, cacheFirst, fastest, cacheOnly, networkOnly
  61. 133.

    #WebPerformance / 9 juin 2018 @guillaumeehret Service worker 5 sw-precache

    module node générant la configuration sw-toolbox lib JS qui fournit des utilitaires pour gérer le cache avec différentes stratégies : networkFirst, cacheFirst, fastest, cacheOnly, networkOnly
  62. 134.

    #WebPerformance / 9 juin 2018 @guillaumeehret 5 Ensemble de librairies

    et d’outils vous aidant à gérer les ressources de vos sites sur les devices de vos utilisateurs - aide à gérer le mode offline ou un réseau défaillant - améliore les performances quand une personne revient sur votre site
  63. 135.

    #WebPerformance / 9 juin 2018 @guillaumeehret 5 SW cache JS

    networkFirst cacheFirst fastest cacheOnly networkOnly
  64. 136.

    #WebPerformance / 9 juin 2018 @guillaumeehret importScripts('workbox-sw.prod.v1.3.0.js'); const workboxSW =

    new self.WorkboxSW({ "cacheId": "dev-mind", "clientsClaim": true }); workboxSW.precache([]); workboxSW.router.registerRoute(/\.(?:png|gif|jpg)$/, workboxSW.strategies.cacheFirst({ cacheName: 'images-cache', cacheExpiration: { maxEntries: 100 } }) ); 5
  65. 137.

    #WebPerformance / 9 juin 2018 @guillaumeehret workboxSW.router.registerRoute('https://fonts.googleapis.com/(.*)', workboxSW.strategies.cacheFirst({ cacheName: 'googleapis',

    cacheExpiration: { maxEntries: 20 }, cacheableResponse: {statuses: [0, 200]} }) ); workboxSW.router.registerRoute('/(.*)', workboxSW.strategies.networkFirst({ cacheName: 'general-cache', cacheExpiration: { networkTimeoutSeconds: 3, maxAgeSeconds: 7200 } })); 5
  66. 138.

    #WebPerformance / 9 juin 2018 @guillaumeehret importScripts('workbox-sw.prod.v1.3.0.js'); const workboxSW =

    new self.WorkboxSW({ "cacheId": "dev-mind", "clientsClaim": true }); workboxSW.precache([]); workboxSW.router.registerRoute(/\.(?:png|gif|jpg)$/, workboxSW.strategies.cacheFirst({ cacheName: 'images-cache', cacheExpiration: { maxEntries: 100 } }) ); 5
  67. 139.

    #WebPerformance / 9 juin 2018 @guillaumeehret const fileManifest = [

    { url: "404.html", revision: "636291341ea1afbfa74a9b26611602bc" }, { url: "blog.html", revision: "b3bcfa57cd425cf053ba8379bacfe41e" }, { url: "index.html", revision: "8f0d94e9b9e3e9550f70c643176c199a" }, { url: "images/logo.svg", revision: "fb715f541f37f38a1350cbd0d4f45f50" }, { url: "styles/app.css", revision: "6b785afae0546dbff97e69ae46ba2af6" }, … ]; workboxSW.precache(fileManifest); 5
  68. 140.

    #WebPerformance / 9 juin 2018 @guillaumeehret 5 SW cache JS

    networkFirst cacheFirst fastest cacheOnly networkOnly
  69. 141.

    #WebPerformance / 9 juin 2018 @guillaumeehret gulp.task('bundle-sw', () => {

    return wbBuild.injectManifest({ swSrc: 'src/sw.js', swDest: 'build/.tmp/service-worker2.js', globDirectory: './build/dist', staticFileGlobs: ['**\/*.{js,html,css,png,jpg,json,gif,svg,webp,eot,ttf,woff,woff2,gz}'] }) .catch((err) => { console.log('[ERROR] This happened: ' + err); }); }); 5
  70. 142.

    #WebPerformance / 9 juin 2018 @guillaumeehret 5 if ('serviceWorker' in

    navigator) { navigator .serviceWorker .register('service-worker.js') .then(registration => { if (typeof registration.update === 'function') { registration.update(); } }) .catch(function(e) { console.error('Error during SW registration:', e); }); }
  71. 144.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  72. 145.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Charger le plus important tout de suite et le reste plus tard
  73. 147.

    #WebPerformance / 9 juin 2018 @guillaumeehret 6 preload <link rel="preload"

    href="styles/app.css" as="style" onload="this.rel='stylesheet'"> <link rel="preload" href="/session/session.html" as="document"> <link rel="preload" href="/app.bundle.js" as="script">
  74. 149.

    #WebPerformance / 9 juin 2018 @guillaumeehret prefetch 6 <link rel="prefetch"

    href="https://fonts.googleapis.com/css?family=Roboto:400" onload="this.rel='stylesheet'">
  75. 150.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  76. 151.

    #WebPerformance / 9 juin 2018 @guillaumeehret preload / prefecth 440ms

    first paint 2.9s loadtime First load 200Kb size 300ms first paint 2.9s loadtime 200Kb size -31% first paint 0% loadtime 0% size 4
  77. 152.

    #WebPerformance / 9 juin 2018 @guillaumeehret Notre objectif first load

    refresh offline 1 < 1s 7.4s first paint 18.2s loadtime 1.6Mb size Départ
  78. 153.

    #WebPerformance / 9 juin 2018 @guillaumeehret Notre objectif first load

    refresh offline 1 < 1s 300ms first paint 2.9s loadtime 200Kb size 220ms 700ms 18Kb first paint loadtime size 17ms 1.2s 0Kb first paint loadtime size 7.4s first paint 18.2s loadtime 1.6Mb size Départ
  79. 154.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Référence https://developers.google.com/web/fundamentals/performance https://github.com/ben-eb/gulp-uncss https://github.com/filamentgroup/loadCSS https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf https://nolanlawson.github.io/frontendday-2016/#1 https://www.youtube.com/watch?v=RWLzUnESylc https://github.com/GoogleChrome/sw-precache https://github.com/GoogleChrome/sw-toolbox https://developer.mozilla.org/fr/docs/Web/API/ServiceWorker https://jakearchibald.com/2014/offline-cookbook/
  80. 155.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 First do it, then do it right, then do it better... Addy Osmani
  81. 156.

    #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 https://github.com/javamind/itogo-webperf Thanks