Inclure du Javascript de manière performante

3 450 vues

Publié le

slide de la mini conférence Performance du 21 juillet 2010
au menu : les 3 stratégies valables pour inclure son JS de manière non bloquante

Publié dans : Technologie
0 commentaire
2 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
3 450
Sur SlideShare
0
Issues des intégrations
0
Intégrations
1 134
Actions
Partages
0
Téléchargements
37
Commentaires
0
J’aime
2
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Inclure du Javascript de manière performante

  1. 1. Inclure du javascript de manière performante Jean-pierre VINCENT Braincracking.org
  2. 2. Orateur Jean-pierre VINCENT En ligne : •braincracking.org (veille) •twitter.com/theystolemynick •jp@vincent.net •google it : jpvincent 10 ans de Web dont : •3 ans de Yahoo! •2 ans d'application Web (timeofmylife.com)
  3. 3. Pourquoi ? rendu rapide = argent bit.ly/perfs_benefice bit.ly/perfs_benefice2
  4. 4. Comment Inclure JS de manière non bloquante (entre autres)
  5. 5. Le fautif <script src="my.js"></script> </head>
  6. 6. Le fautif <script src="my.js"></script> </head> •bloque ce qui vient après : •rendu
  7. 7. Le fautif <script src="my.js"></script> </head> •bloque ce qui vient après : •rendu •exécution
  8. 8. Le fautif <script src="my.js"></script> </head> •bloque ce qui vient après : •rendu •exécution •téléchargement
  9. 9. Le fautif <script src="my.js"></script> </head> •bloque ce qui vient après : •rendu •exécution •téléchargement •IE6-7 : un seul JS à la fois
  10. 10. exemple réservation voyages-sncf.com : •HTML obtenu en 200ms (!)
  11. 11. exemple réservation voyages-sncf.com : •HTML obtenu en 200ms (!) •certains CSS arrivent en 50ms (!!) (je voudrais bien jouer avec ce ping là)
  12. 12. exemple réservation voyages-sncf.com : •HTML obtenu en 200ms (!) •certains CSS arrivent en 50ms (!!) (je voudrais bien jouer avec ce ping là) •au final : 2s de page blanche #fail bit.ly/perfs_sncf
  13. 13. Objectif remplacer <script src="my.js"></script> </head>
  14. 14. Alternatives •Inline
  15. 15. Alternatives •Inline •Bottom
  16. 16. Alternatives •Inline •Bottom •DOM
  17. 17. Alternatives que des désavantages
  18. 18. Alternatives que des désavantages mais
  19. 19. Alternatives que des désavantages mais non bloquant (= argent)
  20. 20. Inline
  21. 21. Inline <script> <?php include('my.js'); ?> </script> </head>
  22. 22. Inline ✓ ordre d'exécution
  23. 23. Inline ✓ ordre d'exécution ✓ dépendances inline
  24. 24. Inline ✓ ordre d'exécution ✓ dépendances inline ✓ non bloquant (ou presque : bit.ly/inline_bloquant)
  25. 25. Inline ✓ ordre d'exécution ✓ dépendances inline ✓ non bloquant (ou presque : bit.ly/inline_bloquant) ✓ document.write()
  26. 26. Inline ✓ ordre d'exécution ✓ dépendances inline ✓ non bloquant (ou presque : bit.ly/inline_bloquant) ✓ document.write() ✓ pas de HTTP
  27. 27. Inline ✓ ordre d'exécution ✓ dépendances inline ✓ non bloquant (ou presque : bit.ly/inline_bloquant) ✓ document.write() ✓ pas de HTTP ✗ pas de cache
  28. 28. Inline Bon pour : •beaucoup de nouveaux visiteurs
  29. 29. Inline Bon pour : •beaucoup de nouveaux visiteurs •peu de JS
  30. 30. Inline Bon pour : •beaucoup de nouveaux visiteurs •peu de JS •bonne bande passante (France)
  31. 31. Inline •évènementielle (jeux-concours)
  32. 32. Inline •évènementielle (jeux-concours) •Homepage, sans cookie •Google Search, Yahoo! (avant) •Netvibes, Facebook
  33. 33. Inline •évènementielle (jeux-concours) •Homepage, sans cookie •Google Search, Yahoo! (avant) •Netvibes, Facebook •pages d'entrées •login •signup
  34. 34. Bottom <script src="my.js"></script> </body>
  35. 35. Bottom
  36. 36. Bottom ✓ ordre d'exécution
  37. 37. Bottom ✓ ordre d'exécution ✓ non bloquant
  38. 38. Bottom ✓ ordre d'exécution ✓ non bloquant ✓ mise en cache
  39. 39. Bottom ✓ ordre d'exécution ✓ non bloquant ✓ mise en cache ✗ dépendances inline
  40. 40. Bottom ✓ ordre d'exécution ✓ non bloquant ✓ mise en cache ✗ dépendances inline ✗ document.write()
  41. 41. Bottom Bon pour les pages dont :
  42. 42. Bottom Bon pour les pages dont : •le contenu textuel est primordial
  43. 43. Bottom Bon pour les pages dont : •le contenu textuel est primordial •le HTML est rapide
  44. 44. Bottom Bon pour les pages dont : •le contenu textuel est primordial •le HTML est rapide •reçoit des visiteurs zappeurs
  45. 45. Bottom Bon pour les pages dont : •le contenu textuel est primordial •le HTML est rapide •reçoit des visiteurs zappeurs •JS est secondaire mais lourd •publicités •widgets
  46. 46. Bottom Type de pages : •Blogs, Journaux
  47. 47. Bottom Type de pages : •Blogs, Journaux •Boutiques
  48. 48. Bottom Type de pages : •Blogs, Journaux •Boutiques •Comparateurs
  49. 49. Bottom Type de pages : •Blogs, Journaux •Boutiques •Comparateurs •...
  50. 50. Bottom - condition 1 contenu principal envoyé en moins de 500ms ?
  51. 51. Bottom - condition 1 contenu principal envoyé en moins de 500ms ? •flush()
  52. 52. Bottom - condition 1 contenu principal envoyé en moins de 500ms ? •flush() •cache serveur
  53. 53. Bottom - condition 1 contenu principal envoyé en moins de 500ms ? •flush() •cache serveur •en premier dans la source
  54. 54. Bottom - condition 2 dépendances JS inline correctibles ?
  55. 55. Bottom - condition 2 dépendances JS inline correctibles ? •mute + eval() : bit.ly/mute_eval
  56. 56. Bottom - condition 2 dépendances JS inline correctibles ? •mute + eval() : bit.ly/mute_eval •hijacking
  57. 57. Bottom - condition 2 dépendances JS inline correctibles ? •mute + eval() : bit.ly/mute_eval •hijacking Si non, modification du JS obligatoire
  58. 58. DOM
  59. 59. DOM function loader(fCallback) { }
  60. 60. DOM function loader(fCallback) { var oScript = document .getElementsByTagName("head")[0] .createElement('script'); }
  61. 61. DOM function loader(fCallback) { var oScript = document .getElementsByTagName("head")[0] .createElement('script'); oScript.src= 'my.js'; }
  62. 62. DOM function loader(fCallback) { var oScript = document .getElementsByTagName("head")[0] .createElement('script'); oScript.src= 'my.js'; oScript.onload = fCallback; oScript.onreadystatechange = fCallback; }
  63. 63. DOM jQuery : $.getScript( 'my.js', fCallback); YUI 3 : Y.Get.script( 'my.js', {onSuccess: fCallback} );
  64. 64. DOM ✓ non bloquant
  65. 65. DOM ✓ non bloquant ✓ mise en cache
  66. 66. DOM ✓ non bloquant ✓ mise en cache ✓ IE6-7 parallélise ! (bit.ly/dom_IE_para)
  67. 67. DOM ✓ non bloquant ✓ mise en cache ✓ IE6-7 parallélise ! (bit.ly/dom_IE_para) ✗ dépendances inline
  68. 68. DOM ✓ non bloquant ✓ mise en cache ✓ IE6-7 parallélise ! (bit.ly/dom_IE_para) ✗ dépendances inline ✗ document.write()
  69. 69. DOM ✓ non bloquant ✓ mise en cache ✓ IE6-7 parallélise ! (bit.ly/dom_IE_para) ✗ dépendances inline ✗ document.write() ✗ ordre d'exécution
  70. 70. DOM Bon pour les pages :
  71. 71. DOM Bon pour les pages : •éligibles à Bottom
  72. 72. DOM Bon pour les pages : •éligibles à Bottom •HTML > 0.5 - 1s ou
  73. 73. DOM Bon pour les pages : •éligibles à Bottom •HTML > 0.5 - 1s ou •gros volume de JS ( > 500k décompressé)
  74. 74. DOM Type de pages : •Blogs, Journaux •Boutiques •Comparateurs •...
  75. 75. DOM Type de pages : •Blogs, Journaux •Boutiques •Comparateurs •... •Applications Web
  76. 76. DOM - préalable Découper son JS en modules
  77. 77. DOM - préalable Découper son JS en modules 1 module PHP = 1 fonctionalité = 1 JS lui donner un identifiant
  78. 78. DOM - préalable ✓ Découper son JS en modules Centraliser les inclusions : MY.loader = function(sScriptID, fCallback) { };
  79. 79. DOM - préalable ✓ Découper son JS en modules Centraliser les inclusions : MY.loader = function(sScriptID, fCallback) { $.getScript( sScriptID+'.js', fCallback); };
  80. 80. DOM - préalable ✓ Découper son JS en modules ✓ Centraliser les inclusions Corriger toutes ses dépendances : <form id="login-form"> ... </form> <
  81. 81. DOM - préalable ✓ Découper son JS en modules ✓ Centraliser les inclusions Corriger toutes ses dépendances : <form id="login-form"> ... </form> <script> MY.enrichForm('login-form'); </script>
  82. 82. DOM - préalable ✓ Découper son JS en modules ✓ Centraliser les inclusions Corriger toutes ses dépendances : <form id="login-form"> ... </form> <script> MY.loader('login-js', function() { MY.enrichForm('login-form'); }); </script>
  83. 83. DOM - préalable ✓ Découper son JS en modules ✓ Centraliser les inclusions ✓ Corriger toutes ses dépendances
  84. 84. DOM - préalable ✓ Découper son JS en modules ✓ Centraliser les inclusions ✓ Corriger toutes ses dépendances ✓ Concaténer les fichiers communs
  85. 85. DOM - évolution ✓ Découper son JS en modules ✓ Centraliser les inclusions ✓ Corriger toutes ses dépendances ✓ Concaténer les fichiers communs Plus tard : •gérer les inclusions multiples
  86. 86. DOM - évolution ✓ Découper son JS en modules ✓ Centraliser les inclusions ✓ Corriger toutes ses dépendances ✓ Concaténer les fichiers communs Plus tard : •gérer les inclusions multiples Tactique YUI3 : •gérer dépendances entre classes
  87. 87. DOM - évolution ✓ Découper son JS en modules ✓ Centraliser les inclusions ✓ Corriger toutes ses dépendances ✓ Concaténer les fichiers communs Plus tard : •gérer les inclusions multiples Tactique YUI3 : •gérer dépendances entre classes •générer les JS à la volée
  88. 88. Etude de cas Netvibes : •inline : 100Ko de JS •DOM : 260Ko de JS •DOM : widget JS
  89. 89. Etude de cas Facebook (Wall) :
  90. 90. Etude de cas Facebook (Wall) : •flush() HTML presque vide
  91. 91. Etude de cas Facebook (Wall) : •flush() HTML presque vide •inline : 1 loader DOM + 1 loader spécial (bigPipe : bit.ly/fb_bigpipe)
  92. 92. Etude de cas Facebook (Wall) : •flush() HTML presque vide •inline : 1 loader DOM + 1 loader spécial (bigPipe : bit.ly/fb_bigpipe) •flush() des modules 1 par 1
  93. 93. Etude de cas Facebook (Wall) : •flush() HTML presque vide •inline : 1 loader DOM + 1 loader spécial (bigPipe : bit.ly/fb_bigpipe) •flush() des modules 1 par 1 •DOM :9 JS chargés (1 principal + 8 modules)
  94. 94. Etude de cas Facebook (Wall) : •flush() HTML presque vide •inline : 1 loader DOM + 1 loader spécial (bigPipe : bit.ly/fb_bigpipe) •flush() des modules 1 par 1 •DOM :9 JS chargés (1 principal + 8 modules) •meme technique pour CSS
  95. 95. Etude de cas YUI 3 :
  96. 96. Etude de cas YUI 3 : •tout appel de code commence dans une fonction de callback
  97. 97. Etude de cas YUI 3 : •tout appel de code commence dans une fonction de callback •liste manuelle des dépendances
  98. 98. Etude de cas YUI 3 : •tout appel de code commence dans une fonction de callback •liste manuelle des dépendances •le loader connait les dépendances et les fichiers déjà chargés
  99. 99. Etude de cas YUI 3 : •tout appel de code commence dans une fonction de callback •liste manuelle des dépendances •le loader connait les dépendances et les fichiers déjà chargés •coté serveur : un combinateur
  100. 100. Orateur Jean-pierre VINCENT En ligne : •braincracking.org (veille) •twitter.com/theystolemynick •jp@vincent.net •google it : jpvincent 10 ans de Web dont : •3 ans de Yahoo! •2 ans d'application Web (timeofmylife.com)

×