Grâce à d'excellents toolkits Javascript [NB1] et à la maturité des navigateurs web, il est possible de donner à un site web en HTML des effets dignes de Flash. Des possibilités qui deviennent envisageables même pour un infographiste ou un intégrateur web, en en connaissant qu'un minimum.

Mais ces bibliothèques peuvent être très lourdes, et leur temps de chargement côté surfeur pénalisent les sites, rendant parfois les navigateurs comateux pendant quelques secondes. Si vous ajoutez les dépendances entre ces scripts, vous pouvez vite atteindre plus de 3 appels (par exemple, sur mon ancien site : prototype.js, scriptaculous.js, effects.js, nicetitle.js, lightbox2.js ,... hem hem)
Si vous ajoutez à la page un Javascript pour un site sociétal (genre Technorati), une bannière de pub (Adsense ou autre) voire plus simplement un bête outil d'analyse trafic par mouchard JS (WebTrends, Google Analytics, Xiti), voire même puisque c'est à la mode des appels Ajax en pagaille... le temps de chargement de votre page devient tributaire d'un serveur tiers. Ce qui veut dire que si ce serveur devient moins réactif parce qu'on est aux heures de pointes, votre site donne une impression sensible de ralentissement, avec un freeze très désagréable du navigateur. Le problème touche tout le monde, frustrant car il ne dépend pas du webdesign... ou plutôt si : Il est possible en reconcevant votre code de supprimer ce méchant lag.

Et je comptais bien le mettre en pratique en redesignant mon site.

Au début des Temps, le Javascript et le HTML étaient mélangés

C'est la méthode la plus ancestrale pour faire appeler un Javascript : En l'attachant à un lien <a href="javascript:code();">. L'avantage, c'est que la balise hyperlien donne une cohérence du GUI. Le problème, c'est que les navigateurs qui n'ont pas Javascript (et à l'époque, ils étaient légion) n'ont que faire de ce lien.

Alors fut introduit la possibilité d'attacher un évènement à une balise. Ainsi, il était possible de créer des boutons qui créent une action <button onclick="code();">. Mais ces actions n'avaient lieu que si une action utilisateur avait effectivement lieue...

Heureusement, fut introduit dans le langage HTML une balise où tout devint possible : <script>
Contrairement à ce que l'on pourrait croire, cette balise n'est pas à l'usage exclusif de Javascript : On peut y inclure du VBscript (pour IE), du Tcl, du Perl (sur moteur Mozilla), selon le code type-mime spécifié dans l'attribut type="" (par défaut, ça reste du Javascript).

Néanmoins, l'affichage de votre page web sera complètement paralysée tant que cette balise ne sera pas intégralement interprétée. Par exemple, sur cette (vieille) page, la fonction alert(); bloque le parser [NB2], qui attend que le petit script rende la main pour afficher le reste du document. Quand l'utilisateur a cliqué sur la boîte de dialogue, le navigateur voit la suite de la page, et donc la balise <style>. C'est très important : cela signifie que votre page n'est pas complètement visible (même complètement chargée dans l'ordinateur du visiteur), puisqu'il faut que le navigateur termine d'interpréter votre Javascript avant de finir l'interprétation de votre document HTML.
Et pourquoi un tel comportement ? Car vous pourriez très bien y faire une construction “dynamique” (plus exactement “brutasse”) de HTML dans votre script via la fonction document.write();. Vous verrez que cette dernière est infâmement fourbe.

Et le Verbe fut <script src​="...

Cette méthode, qui est unanimement considérée comme la plus propre et la plus standard (j'ai déjà expliqué pourquoi), permet d'utiliser des scripts globaux à l'ensemble ou une partie importante d'un site web. Idéalement, il est placé dans la section <head> du document HTML.

Néanmoins, elle a exactement le même impact côté client qu'un script embarqué : Le navigateur arrêtera tout traitement de la page (et donc bloque son affichage), tant qu'il n'a pas intégralement reçu le programme Javascript et qu'il ai traité les fonctions appelées.
Alors qu'en temps normal la plupart des navigateurs modernes ouvrent 4 chargements en simultanée (en mode asynchrone), on passe dans un système digne de nos plus Vaillantes Administration où chacun attend son tour que le chiffre imprimé sur son ticket soit annoncé au haut-parleur : Dans le cas de mon ancien site, ce n'est qu'une fois prototype.js chargé et interprété en entier qu'on passe à effects.js... et ainsi de suite jusqu'à google-analytics.js, et enfin les images se chargent... mais par paquet de 4, sans s'attendre mutuellement.

À noter que l'attribut defer dans la balise permet d'éviter cette attente. Si évidemment votre navigateur la supporte [NB3], et à condition de bannir tout document.write(); et toute dépendance entre les scripts. Pour mon exemple, c'est loupé.

<script src​=" juste à la Fin du HTML

Durant sa période de béta-testing, Google Analytics fut victime d'une panne. Le serveur google-analytics.com hébergeant le programme urchin.js étant indisponible, l'ensemble des pages de leurs clients béta-testeurs furent inaccessibles pendant 24 heures. Le temps que le navigateur du visiteur attende le timeout (en général, une bonne minute), tous les sites qui utilisaient ce service ne furent que pages blanches... Car à ce moment-là, Saint Google avait décrété que son outil de confession devait être invoqué pieusement par le HTML dans la balise <head>
Conscients de ce souci, G.A. recommanda alors de ne plus appeler leur script entre les balises <head>, mais juste avant </body>.

Mais alors, se dit le lecteur, pourquoi pas entre </body> et </html> ? Parce que le code ne serait plus valide. Ça peut pas. Pas bien. Faut pas. Saimal. Sapu.

Sauf que...
Sauf que la position idéale, si on va dans l'idée de faire un appel à un .js unique, c'est à côté des CSS [NB4], c'est-à-dire dans la balise <head>...

Prenez mon body et onloadez-le

Revenons au principe d'attacher une fonction JS à une balise HTML.
Et là, on s'est dit qu'il suffisait d'invoquer les éléments lourds non pas dans la fonction principale du .js (équivalent au rôle de la section main(); en C), mais lors de l'évènement onload de la balise <body>. Ce qui veut dire que soit on l'appelle dans le HTML par <body onload=" (je rappelle que cette méthode, c'est caca.), soit en liant une fonction en javascript :
window.onload = function () {} [NB5]

Néanmoins, l'évènement onload est intrinsèquement lié au chargement complète de sa balise et de tous ses enfants. Ce qui veut dire que cet évènement l'a lieu qu'après que l'ensemble des éléments comme les images <img />, les images décrites dans la/les CSS, les <object />, <iframe /> et bien évidemment <script /> soient effectivement chargés.

Cette solution garanti qu'aucun blocage ne sera dû à l'absence quelconque de quoi que se soit, sinon.... du visiteur ! Car il est parfois utile de comptabiliser au plus vite votre visiteur : pour gonfler vos statistiques de trafic “naturellement”, pour imprimer plus de pages de publicités vues, etc... Si possible, avant les deux secondes où il va s'apercevoir qu'il n'est pas sur le site qu'il attendait.[NB6]

Time is money, et attendre onload pourrait en faire perdre pas mal

Un <script src​="" /> unique, avec le tentateur document.write();

En fait, le coup/coût idéal serait de n'avoir à faire appel qu'à une seule balise <script src="" /> dans son document HTML, laquelle appelle ses petites copines javascripteuses pour bricoler leurs petits effets. Lightbox, Nicetitle, Analytics, AdSense...
Ça simplifierait de plus le développement, puisqu'il suffit de modifier une unique adresse pour, par exemple, changer complètement de toolkit. Une approche qui ressemble à celle de la création de CSS sur un site en ligne.

Or voilà exactement ce que je déteste : du document.write(); en vrac.
D'après vous, que se passe-t-il quand cette fonction est utilisée ? Le nouveau HTML est parsé, chargeant un Javascript qui est interprété, ralentissant d'autant l'affichage de votre page. Si vous tentez de retarder (avec la méthode .onload ou un setTimeout();) une fonction qui utilisera document.write();, vous n'êtes absolument pas sûr du résultat... pouvant même parfois effacer complètement votre document HTML... En clair : c'est une MAUVAISE SOLUTION.

À noter que cette solution proposée par l'équipe IE était tellement bugguée (surtout que la bonne réponse était CDATA), qu'elle a mené à une suite intéressante de réponses dans le blog de Gervase Markham (de l'équipe Firefox). Ce qui m'a amené (et je suis pas le seul) à une solution évidente :

Un seul src= et sur ce script je construirais mon DOM

Or donc, appelé à deviser là-dessus, Alan Trick le biennommé propose dans les commentaires d'utiliser une construction via l'arbre DOM du document. Avantages : Le parser du navigateur n'a plus à attendre et continue pépèrement à montrer le HTML, le chargement du source externe se fait en asynchrone (et donc indépendemment des temps d'attente),... bref tout le monde il est content. Pour ceux qui ont besoin de dépendances, Dao/Design-Noir propose une chouette bibliothèque extrèmement légère (moins de 30 lignes ! pensez-donc !) qui gère les listes d'attente et l'exécution de fonctions une fois la bibliothèque chargée... D'ailleurs, c'est comme ça qu'il colorise son code source.

Une solution efficace, mais qui dans des cas rarissimes, vous vaudra de vous fritter avec la susceptibilité légendaire de MSIE. Rien que ce domaine vaut un autre chapitre, qui racontera comment j'ai appris plein de nouveaux gros-mots que blogguent ouvertement les développeurs de ASP.NET contre leurs collègues de IE.

Mais avant ça, il faudra que je vous cause comment encore optimiser votre Javascript : En tassant son code au DocMartens™ !


Petits textes explicatifs avant de fermer le </body>

  1. Toolkit : Bibliothèque de fonction agissant comme de véritables environnements de développement. Ils étendent le langage, comble des déficiences, installent des fonctions primitives rébarbatives à ré-écrire à chaque fois. La mort du Bénédictin.
  2. Parser : Logiciel qui analyse syntaxiquement un document texte afin d'exécuter le programme qu'il contient (Javascript, Basic,...), construire sa mise en forme (HTML, XML, OpenOffice,...), ou les macros d'aspect (CSS, les thèmes de Firefox, Word, OpenOffice,...). Généralement, c'est bourré de regex, voire écrit dans le plus incompréhensible des Perl parce que celui qui l'a écrit ne peut pas saquer son collègue en face...
  3. ↑ defer : Même si elle est décrite dans la norme HTML4 par le W3C, cet attribut ne semble supporté que par MSIE. Pour une fois que l'équipe de Microsoft est en avance sur les autres pour appliquer les normes et standards, elle a dû sabrer le champagne. Je me demande si c'est arrivé une autre fois depuis 1998...
  4. ↑ les CSS : Certains mécréants n'ont pas encore compris l'utilité de la CSS unique, choyée et bichonnée comme l'unique héritier mâle des nombreuses familles Chinoises... Faudrait que je parte en croisade aussi là-dessus.
  5. ↑ window.onload : On peut écrire indifféremment window.onload ou document.onload ... les différences entre les deux éléments sont relativement minimes, et àmha ne concernent que la présence de <frame /> dans votre code.
  6. ↑ mesure d'audience : À ce sujet, I télé diffuse parfois un “bumper” pour vanter leurs XX millions de télespectateurs mensuel... Un chiffre parfaitement juste car il s'agit de personnes restant au moins une seconde sur leur chaîne. Le temps d'éternuer en zappant...
    Questions chiffres, Bertrand Renard arrive à retenir ses télespectateurs autrement...