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

ITOGO_Conf_-_Optimiser_les_performances_d_une_w...

 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

Dev-Mind

June 11, 2018
Tweet

More Decks by Dev-Mind

Other Decks in Technology

Transcript

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

    juin 2018 Optimiser les performances d’une webapp
  2. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Pourquoi une webapp doit être performante ?
  3. #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. #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. #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. #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. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Que faire pour créer des webapps performantes ?
  8. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 https://www.dev-mind.fr Développement Formations
  9. #WebPerformance / 9 juin 2018 @guillaumeehret avec des crêpes et

    du coeur 19 et 20 avril 2018 à Lyon https://mixitconf.org/
  10. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  11. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  12. #WebPerformance / 9 juin 2018 @guillaumeehret loadtime https://monsite/ HTML parsing

    parsing compile render JavaScript Autres CSS render JavaScript Autres CSS ... 1
  13. #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. #WebPerformance / 9 juin 2018 @guillaumeehret Mes outils pour mesurer

    Webpagetest >> Pagespeed Insight >> Browser developper tools (Lighthouse) ... 1
  15. #WebPerformance / 9 juin 2018 @guillaumeehret Avant de commencer 2

    7.4s first paint 18.2s loadtime Sans optim 1.6Mb size
  16. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  17. #WebPerformance / 9 juin 2018 @guillaumeehret <html> <head> <script .../>

    <body> <script .../> </body </html> JavaScript HTML 2
  18. #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. #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. #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. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  22. #WebPerformance / 9 juin 2018 @guillaumeehret 3 Minification ressources txt

    JavaScript HTML sur mon exemple -22% -51% -26% CSS
  23. #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. #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. #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. #WebPerformance / 9 juin 2018 @guillaumeehret 3 Le texte se

    compresse CSS JavaScript HTML JSON les navigateurs acceptent le gzip
  27. #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. #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. #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. #WebPerformance / 9 juin 2018 @guillaumeehret 3 Quelques astuces Modularité

    frameworks Apprenez CSS CSS is awesome de Igor Laborie Nettoyage automatique avec uncss CSS
  31. #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. #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. #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. #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. #WebPerformance / 9 juin 2018 @guillaumeehret webp expérimentation jpeg 2000

    jpeg_xr BPG Utilisez un format alternatif 3 Images
  36. #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
  37. #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
  38. #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. #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
  40. #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
  41. #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
  42. #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
  43. #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
  44. #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
  45. #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
  46. #WebPerformance / 9 juin 2018 @guillaumeehret medium article Osmany, 2017

    Evaluation et parsing d’un script JavaScript de 1Mo 3 JavaScript
  47. #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'; }
  48. #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
  49. #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
  50. #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
  51. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  52. #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
  53. #WebPerformance / 9 juin 2018 @guillaumeehret Cache serveur Cloud base

    de données ou I/O Temps fluctuant Abtraction Spring @Cacheable 4
  54. #WebPerformance / 9 juin 2018 @guillaumeehret 4 Cache busting Versionner

    vos fichiers de ressources Pour le HTML limitez le max-age
  55. #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
  56. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  57. #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
  58. #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
  59. #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
  60. #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
  61. #WebPerformance / 9 juin 2018 @guillaumeehret 5 SW cache JS

    networkFirst cacheFirst fastest cacheOnly networkOnly
  62. #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
  63. #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
  64. #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. #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
  66. #WebPerformance / 9 juin 2018 @guillaumeehret 5 SW cache JS

    networkFirst cacheFirst fastest cacheOnly networkOnly
  67. #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
  68. #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); }); }
  69. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  70. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Charger le plus important tout de suite et le reste plus tard
  71. #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">
  72. #WebPerformance / 9 juin 2018 @guillaumeehret prefetch 6 <link rel="prefetch"

    href="https://fonts.googleapis.com/css?family=Roboto:400" onload="this.rel='stylesheet'">
  73. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 Mesurer Transporter Limiter Cacher Offline Anticiper 1 6 2 5 4 3
  74. #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
  75. #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
  76. #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
  77. #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/
  78. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

    juin 2018 First do it, then do it right, then do it better... Addy Osmani
  79. #WebPerformance / 9 juin 2018 @guillaumeehret @guillaumeehret #WebPerformance / 9

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