IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contributions JavaScript / AJAX Discussion :

Où placer les balises script dans le code de la page HTML ? [FAQ]


Sujet :

Contributions JavaScript / AJAX

  1. #1
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut Où placer les balises script dans le code de la page HTML ?
    En remplacement de http://javascript.developpez.com/faq...positionScript , entrée à laquelle j'ai moi-même participé, je propose une réponse plus complète introduisant les attributs async et defer. J'ai repris les explications de ce post:
    http://www.developpez.net/forums/d15...y/#post8371661

    Voilà la proposition:

    TL;DR: si vous ne devez retenir qu'une seule option à appliquer en toutes circonstances, mettre tous les <script> dans <head> avec l'attribut defer est le meilleur compromis à toutes les situations exposées ci-dessous.

    Plus un script est déclaré haut dans le code HTML d'un document, plus tôt le navigateur lancera la requête pour le télécharger. En effet, le navigateur n'attend pas que tout le document soit chargé: le HTML est interprété progressivement à mesure qu'il est reçu par le navigateur. C'est la même chose pour les feuilles CSS et pour toute autre ressource de la page. Bien sûr, la différence est significative uniquement si on a de gros documents, des pages HTML de plusieurs centaines de Ko. Si on regarde comment le Web a évolué, le HTML est aujourd'hui généralement bien plus léger que le reste (gros frameworks JS, CSS à rallonge, images haute définition etc...). Autrement dit, cette question du positionnement des balises <script> n'est plus si importante que ça.

    S'il faut quand même répondre à la question du positionnement optimal des balises <script>, voilà la théorie :

    1. 1ère règle: les ressources importantes, c'est-à-dire celles qu'on souhaite avoir avant même que le document n'ait fini d'être téléchargé, doivent être idéalement placées dans <head>. C'est pour cette raison que l'on met les feuilles de style en <head>, pour avoir le document "décoré" tout de suite et éviter que l'utilisateur ne voit la page sans styles jusqu'à ce que le chargement de la page soit fini.
    2. 2ème règle: exception à cette 1ère règle: un script étant susceptible de modifier le contenu de la page, il est nécessaire de bloquer l'interprétation de la page pendant le chargement et l'exécution des scripts ; placer les scripts dans le <head> réduit ainsi la vitesse d'affichage de la page. On doit ce comportement notamment à document.write qui peut venir modifier le document avant-même que celui ait fini d'être chargé. Précision importante, ce qui est bloqué est seulement l'interprétation du HTML, pas son téléchargement qui continue en tâche de fond. Tous les navigateurs modernes savent très bien gérer ça maintenant, donc le temps de chargement total de la page est quasiment inchangé. En revanche, le délai d'attente avant que l'utilisateur commence à voir un bout de contenu de page est lui plus long, car conditionné par le chargement et l'exécution des scripts en <head>.
    3. 3ème règle, contre-exception : les attributs async et defer apparus avec HTML5 sur la balise <script> permettent de mieux gérer ce comportement de blocage du parser HTML, et donc d'avoir les gains de la 1ère règle sans les pertes de la 2ème règle.


    Voilà pour la théorie. Qu'est-ce que cela donne en pratique ?

    • si vous devez supporter des navigateurs non compatibles HTML5, avez des pages HTML assez grosses et que votre site ne repose pas sur JavaScript pour fonctionner, mettez vos scripts avant la fermeture du </body>
    • si vous devez supporter des navigateurs non compatibles HTML5, avez des scripts assez lourds et importants pour faire fonctionner le site, mettez vos scripts dans le <head>
    • si vous supportez uniquement les navigateurs compatibles HTML5, mettez tous vos scripts dans <head> et :
      • Si le script dépend ou est requis par d'autres scripts, ou s'il doit travailler sur le DOM une fois chargé, ajoutez l'attribut defer.
      • Si le script est indépendant et fonctionnera peu importe quand il est interprété, ajoutez l'attribut async. (exemple: monitoring, statistiques, pub...)


    Dans le cas des scripts utilisant jQuery, la principale raison pour laquelle on met leurs balises <script> juste avant la fermeture du </body>, c'est que l'on est sûrs que le DOM ( le modèle document constitué par le HTML qui précède) a été interprété et on peut donc utiliser les sélecteurs jQuery sans problème. Mais ce n'est pas une obligation, on peut très bien mettre le script en <head> et utiliser $(document).ready (https://api.jquery.com/ready/) pour savoir quand le DOM est prêt.

    Autres liens explicatifs :
    https://developer.mozilla.org/fr/doc...Element/script
    http://www.growingwiththeweb.com/201...ttributes.html
    Votre avis ? Je sais que c'est un sujet à débat, et pas forcément un débat très intéressant. Mais pour être objectif il faut rentrer dans les détails.
    One Web to rule them all

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Ajouté à la FAQ collaborative. Mais je peux encore la modifier si vous avez des retours.
    One Web to rule them all

  3. #3
    Expert éminent sénior

    Avatar de vermine
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6 582
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6 582
    Points : 79 912
    Points
    79 912
    Par défaut
    Merci.

    Tu cites jQuery mais ne vaudrait-il mieux pas parler des frameworks au sens large ? J'ai peur d'un amalgame entre jQuery et le JavaScript par les néophytes.

  4. #4
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    En fait, beaucoup de frameworks peuvent être injectés dans le <head> et s'initialiser eux-mêmes au DOMContentLoaded. jQuery est un peu l'exception puisque c'est au développeur de faire ça manuellement. Et comme il est toujours très populaire et bat à plat de couture toutes les autres libs/fwks, j'ai pensé que ça valait le coup d'en faire un paragraphe. Mais on peut retirer ce paragraphe si tu préfères.
    One Web to rule them all

  5. #5
    Expert éminent sénior

    Avatar de vermine
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6 582
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6 582
    Points : 79 912
    Points
    79 912
    Par défaut
    Non, pas le retirer. Je l'aurais bien mis dans une cadre "Information" mais je ne pense pas que ça existe sur cette page.

  6. #6
    Expert éminent sénior

    Avatar de vermine
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6 582
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6 582
    Points : 79 912
    Points
    79 912
    Par défaut
    Sylvain,

    Nous pourrions peut-être imiter ce comportement pour insérer des zones d'info : http://javascript.developpez.com/faq...un-tableau-PHP

    A savoir, un tableau de deux colonnes avec l'image info des articles. C'est ce qui a été généré automatiquement. De manière générale, je suis un peu déçu par le rendu des pages collaboratives mais à nous de trouver la meilleure présentation.

  7. #7
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Je t'avoue que j'ai essayé de faire ça avec les boutons tableau de l'éditeur bbcode, mais c'était pas probant. Et mon côté semantic-lover en prend un coup Mais je t'en prie, fais tes essais et dis-moi ce qu'on garde au final.
    One Web to rule them all

  8. #8
    Membre expérimenté
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Points : 1 715
    Points
    1 715
    Billets dans le blog
    1
    Par défaut
    J'arrive après la bataille désolé!

    Je n'ai pas grand chose à dire car l'explication est plutôt excellente (comme souvent avec Sylvain).
    Je rajouterais 2-3 petites précisions pour les débutants peut-être:
    • En effet, le navigateur n'attend pas que tout le document soit chargé: le HTML est interprété progressivement à mesure qu'il est reçu par le navigateur.
      => En effet, le navigateur n'attend pas que tout le document soit chargé: le HTML est interprété progressivement à mesure qu'il est reçu par le navigateur (et donc de haut en bas du fichier).
    • defer permet d'attendre que le DOM soit chargé (= que le HTML soit interprété) avant d'exécuter le script.
    • async permet de charger et d'interpréter de manière asynchrone (donc en parallèle de l'interprétation du HTML) le script.

    Après peut-être considères-tu que c'est hors de propos pour cette FAQ.

    2 petites typo que j'ai relevé également:

    • que celui-ci ait fini d'être chargé

    • c'est que l'on est sûrs que le DOM
      (perso je changerais cette phrase en "c'est que l'on veut s'assurer que le DOM")


    Sinon, j'ai une question pour toi Sylvain:
    As-tu un retour sur la compatibilité de defer avec les autres navigateurs que Firefox?


    {gnu: ["um", "cki"]}

  9. #9
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Yes, voilà le support : http://caniuse.com/#search=defer

    Comme tu le vois, c'est assez bien supporté. Et pour les autres navigateurs, ça n'a pas d'importance: si l'attribut n'est pas supporté, on retrouve l'ancien cas de scripts bloquants exécutés dans l'ordre. On perd juste en performances, mais tout fonctionne impeccable.

    Je fais les modifs ortho/formulation dès que je peux.
    One Web to rule them all

  10. #10
    Membre expérimenté
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Points : 1 715
    Points
    1 715
    Billets dans le blog
    1
    Par défaut
    Super, merci pour le lien! Je vais plus l'utiliser alors (j'étais déjà un adepte d'async)!
    Au pire, c'est vrai que ce n'est pas bloquant à moins que tu ne comptes sur ce mécanisme pour JQuery par ex. A ce propos, tu me confirmes que ça peut remplacer le wrapping $(document).ready à 100%?
    {gnu: ["um", "cki"]}

  11. #11
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Non, tu as mal compris. defer ne sert pas à exécuter un script au DOMContentLoaded. defer permet uniquement d'empêcher le blocage du parser HTML pendant le chargement du script. Si tu veux sélectionner en JS des éléments initialement présents dans le DOM, tu auras toujours besoin de te brancher sur DOMContentLoaded ou de mettre ta balise script à la fermeture </body>.

    Je n'ai pas compris ce que tu voulais dire par "à moins que tu ne comptes sur ce mécanisme pour jQuery". defer ne bloque rien, il assure juste que les scripts soient exécutés dans l'ordre de leur déclaration.
    One Web to rule them all

  12. #12
    Membre expérimenté
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Points : 1 715
    Points
    1 715
    Billets dans le blog
    1
    Par défaut
    MDN:
    defer
    Cet attribut booléen permet d'indiquer au navigateur si le script doit être exécuté après l'analyse du document.
    Pour moi cet argument servait à attendre que le DOM soit chargé avant d'exécuter le script. Ai-je mal compris quelque chose?

    defer permet uniquement d'empêcher le blocage du parser HTML pendant le chargement du script
    Ce fonctionnement que tu décris était plutôt le rôle d'async pour moi qui sert à charger et interpréter un script de manière asynchrone et donc en parallèle de l'interprétation du document principal.

    à moins que tu ne comptes sur ce mécanisme pour jQuery
    C'est en relation avec ce que je pensais: si je compte que le DOM soit chargé grâce à defer mais que ce n'est pas le cas car le navigateur ne le gère pas alors j'exécuterai mon script avant que le DOM ne soit chargé et ça risque de ne pas marcher.
    {gnu: ["um", "cki"]}

  13. #13
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Hmm j'imagine que puisqu'il empêche le blocage du parser HTML, celui-ci peut interpréter le reste du document avant l'exécution du script. De là à le confondre avec l'évènement DOMContentLoaded, j'en suis moins sûr. Il est possible que côté implémentation les navigateurs aient confondu ça avec le déclenchement de l'évènement DOMContentLoaded. De toute manière, dans 99% des cas le document HTML est plus rapide à charger que la source du script externe, donc on ne fait pas la différence. J'ai essayé de trouver la réponse dans la spec HMTL5 officielle mais c'est un sacré fouillis: https://www.w3.org/TR/html5/scripting-1.html

    The exact processing details for these attributes are, for mostly historical reasons, somewhat non-trivial, involving a number of aspects of HTML. The implementation requirements are therefore by necessity scattered throughout the specification. The algorithms below (in this section) describe the core of this processing, but these algorithms reference and are referenced by the parsing rules for scriptstart and end tags in HTML, in foreign content, and in XML, the rules for the document.write() method, the handling of scripting, etc.
    Pour en être sûr, il faudrait faire des tests avec des documents HTML très importants comparés à de petits scripts. Mais j'ai peur que ce détail d'implémentation varie entre navigateurs. Dans le doute, je préfère continer à utiliser DOMContentLoaded.
    One Web to rule them all

  14. #14
    Membre expérimenté
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Points : 1 715
    Points
    1 715
    Billets dans le blog
    1
    Par défaut
    Effectivement ça n'a pas l'air très simple de trouver l'information. Merci d'avoir cherché en tout cas!
    Si je pense à le faire je testerai sur un Firefox et un Chromium pour voir. Je te dirais ce que j'observe.

    Dans le doute, je préfère continer à utiliser DOMContentLoaded.
    Je suis assez d'accord avec toi.
    {gnu: ["um", "cki"]}

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Balise script dans le head de la page html
    Par binouzzz19 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 08/07/2010, 09h30
  2. Du PHP dans les balises "script"
    Par coachllb dans le forum Langage
    Réponses: 5
    Dernier message: 28/07/2007, 18h55
  3. Balise div dans le code .NET
    Par the big ben 5 dans le forum Delphi .NET
    Réponses: 1
    Dernier message: 26/04/2006, 17h35
  4. [//TODO] Comment voir les balises TODO dans les problemes?
    Par romain3395 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 06/12/2004, 08h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo