web-dev-qa-db-fra.com

Où devrais-je placer les balises <script> dans le balisage HTML?

Lors de l'intégration de JavaScript dans un document HTML, quel est le bon emplacement pour placer les balises <script> et JavaScript inclus? Il me semble rappeler que vous n'êtes pas censé les placer dans la section <head>, mais le placer au début de la section <body> est également mauvais, car JavaScript doit être analysé avant le rendu complet de la page (ou quelque chose du genre). ). Cela semble laisser le end de la section <body> comme emplacement logique pour les balises <script>.

Alors, où est le bon endroit pour mettre les balises <script>?

(Cette question fait référence à cette question , dans laquelle il a été suggéré de déplacer les appels de fonctions JavaScript des balises <a> aux balises <script>. J'utilise spécifiquement jQuery, mais des réponses plus générales sont également appropriées.)

1276
mipadi

Voici ce qui se passe lorsqu'un navigateur charge un site Web avec une balise <script>:

  1. Récupérer la page HTML (par exemple, index.html)
  2. Commencer à analyser le HTML
  3. L'analyseur rencontre une balise <script> faisant référence à un fichier de script externe.
  4. Le navigateur demande le fichier de script. Pendant ce temps, l'analyseur bloque et arrête l'analyse de l'autre HTML sur votre page.
  5. Après un certain temps, le script est téléchargé et ensuite exécuté.
  6. L'analyseur continue d'analyser le reste du document HTML.

L'étape 4 provoque une mauvaise expérience utilisateur. Votre site Web cesse de charger jusqu'à ce que tous les scripts soient téléchargés. S'il y a une chose que les utilisateurs détestent, c'est d'attendre le chargement d'un site Web.

Pourquoi cela arrive-t-il?

Tout script peut insérer son propre code HTML via document.write() ou d'autres manipulations DOM. Cela implique que l'analyseur doit attendre que le script ait été téléchargé et exécuté avant de pouvoir analyser en toute sécurité le reste du document. Après tout, le script pourrait avoir inséré son propre HTML dans le document.

Cependant, la plupart des développeurs JavaScript ne manipulent plus le DOM while que le document est en train de charger. Au lieu de cela, ils attendent que le document ait été chargé avant de le modifier. Par exemple:

<!-- index.html -->
<html>
    <head>
        <title>My Page</title>
        <script type="text/javascript" src="my-script.js"></script>
    </head>
    <body>
        <div id="user-greeting">Welcome back, user</div>
    </body>
</html>

Javascript:

// my-script.js
document.addEventListener("DOMContentLoaded", function() { 
    // this function runs when the DOM is ready, i.e. when the document has been parsed
    document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});

Parce que votre navigateur ne sait pas que my-script.js ne modifiera pas le document tant qu'il n'aura pas été téléchargé et exécuté, l'analyseur arrête l'analyse.

Recommandation vieillie

L'ancienne approche pour résoudre ce problème consistait à placer les balises <script> au bas de votre <body>, car cela garantit que l'analyseur n'est pas bloqué jusqu'à la toute fin. 

Cette approche a son propre problème: le navigateur ne peut pas commencer à télécharger les scripts tant que tout le document n'est pas analysé. Pour les sites Web de grande taille dotés de scripts et de feuilles de style volumineux, il est très important de pouvoir télécharger le script dès que possible. Si votre site Web ne se charge pas dans les 2 secondes, les internautes accèdent à un autre site Web.

Dans une solution optimale, le navigateur commence à télécharger vos scripts dès que possible, tout en analysant le reste de votre document.

L'approche moderne

Aujourd'hui, les navigateurs prennent en charge les attributs async et defer dans les scripts. Ces attributs indiquent au navigateur qu'il est prudent de poursuivre l'analyse pendant le téléchargement des scripts.

async

<script type="text/javascript" src="path/to/script1.js" async></script>
<script type="text/javascript" src="path/to/script2.js" async></script>

Les scripts avec l'attribut async sont exécutés de manière asynchrone. Cela signifie que le script est exécuté dès son téléchargement, sans bloquer le navigateur entre-temps.
Cela implique qu'il est possible de télécharger et exécuter le script 2 avant le script 1. 

Selon http://caniuse.com/#feat=script-async , 94,57% des navigateurs le supportent.

reporter

<script type="text/javascript" src="path/to/script1.js" defer></script>
<script type="text/javascript" src="path/to/script2.js" defer></script>

Les scripts avec l’attribut de report sont exécutés dans l’ordre (c’est-à-dire le premier script 1, puis le script 2). Cela ne bloque pas non plus le navigateur.

Contrairement aux scripts asynchrones, les scripts de report ne sont exécutés qu'après le chargement de l'intégralité du document.

Selon http://caniuse.com/#feat=script-defer , 94,59% des navigateurs le supportent. 94,92% le soutiennent au moins partiellement.

Une remarque importante sur la compatibilité du navigateur: dans certaines circonstances, IE <= 9 peut exécuter des scripts différés dans le désordre. Si vous avez besoin de supporter ces navigateurs, veuillez lire this first!

Conclusion

L’état actuel de la technique consiste à placer des scripts dans la balise <head> et à utiliser les attributs async ou defer. Cela permet à vos scripts d'être téléchargés dès que possible sans bloquer votre navigateur.

La bonne chose est que votre site Web doit toujours se charger correctement sur les 6% de navigateurs qui ne prennent pas en charge ces attributs tout en accélérant les 94% restants.

1606
Bart

Juste avant la balise de fermeture du corps, comme indiqué sur

http://developer.yahoo.com/performance/rules.html#js_bottom

Mettez les scripts en bas

Le problème posé par les scripts est qu'ils bloquent les téléchargements parallèles. La spécification HTTP/1.1 suggère que les navigateurs ne téléchargent pas plus de deux composants en parallèle par nom d'hôte. Si vous diffusez vos images à partir de plusieurs noms d'hôte, vous pouvez effectuer plus de deux téléchargements en parallèle. Cependant, pendant le téléchargement d'un script, le navigateur ne lance aucun autre téléchargement, même avec des noms d'hôte différents. 

224
Cammel

Les balises de script non bloquantes peuvent être placées à peu près n'importe où:

<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
  • async script sera exécuté de manière asynchrone dès qu'il sera disponible
  • defer script est exécuté lorsque l'analyse du document est terminée
  • async defer le script revient au comportement différé si async n'est pas pris en charge

Ces scripts seront exécutés de manière asynchrone/après que le document soit prêt, ce qui signifie que vous ne pouvez pas le faire:

<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
  * might throw "jQuery is not defined" error
  * defer will not work either
-->

Ou ca:

<script src="document.write(something).js" async></script>
<!--
  * might issue "cannot write into document from an asynchronous script" warning
  * defer will not work either
-->

Ou ca:

<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
  * might throw "jQuery is not defined" error (no guarantee which script runs first)
  * defer will work in sane browsers
-->

Ou ca:

<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
  * might not locate #header (script could fire before parser looks at the next line)
  * defer will work in sane browsers
-->

Cela dit, les scripts asynchrones offrent les avantages suivants:

  • Téléchargement parallèle de ressources:
    Browser peut télécharger des feuilles de style, des images et d’autres scripts en parallèle sans attendre qu’un script soit téléchargé et exécuté.
  • Indépendance de l'ordre source:
    Vous pouvez placer les scripts à l’intérieur de la tête ou du corps sans craindre le blocage (utile si vous utilisez un CMS) L'ordre d'exécution reste cependant important.

Il est possible de contourner les problèmes d'ordre d'exécution en utilisant des scripts externes prenant en charge les rappels. De nombreuses API JavaScript tierces prennent désormais en charge une exécution non bloquante. Voici un exemple de chargement de l'API Google Maps de manière asynchrone .

64
Salman A

Le conseil standard, promu par Yahoo! L'équipe Performance exceptionnelle consiste à placer les balises <script> à la fin du corps du document afin qu'elles ne bloquent pas le rendu de la page.

Toutefois, certaines approches plus récentes offrant de meilleures performances sont décrites dans cette réponse concernant le temps de chargement du fichier JavaScript de Google Analytics:

Il y a quelques super slides par Steve Souders (expert en performance côté client) sur:

  • Différentes techniques pour charger des fichiers JavaScript externes en parallèle
  • leur effet sur le temps de chargement et le rendu de la page
  • type d'indicateurs "en cours" affichés par le navigateur (par exemple, "chargement" dans la barre d'état, curseur de souris en sablier).
36
orip

Si vous utilisez JQuery, placez le javascript là où vous le trouvez le mieux et utilisez $(document).ready() pour vous assurer que tout est correctement chargé avant d'exécuter une fonction.

Sur une note de côté: j'aime toutes mes balises de script dans la section <head>, car cela semble être l'endroit le plus propre.

22
Andrew Hare

XHTML ne sera pas validé si le script se trouve ailleurs que dans l'élément head. se trouve que ça peut être partout.

Vous pouvez différer l'exécution avec quelque chose comme jQuery, de sorte que son emplacement n'a pas d'importance (sauf pour une petite performance lors de l'analyse).

9
Allain Lalonde
<script src="myjs.js"></script>
</body>

la balise script doit toujours être utilisée avant body close ou Bottom dans le fichier HTML.

alors vous pouvez voir le contenu de la page avant de charger le fichier js.

cochez cette case si besoin: http://stevesouders.com/hpws/rule-js-bottom.php

8
AmanKumar

La réponse conventionnelle (et largement acceptée) est "en bas", car alors le DOM entier aura été chargé avant que tout ne puisse commencer à s'exécuter.

Il existe des dissidents, pour diverses raisons, à commencer par la pratique disponible consistant à commencer intentionnellement l'exécution avec un événement page onload.

5
dkretz

Selon le script et son utilisation, le meilleur possible (en termes de chargement de page et de temps de rendu) peut consister à ne pas utiliser de balise <script> conventionnelle en soi, mais à déclencher de manière dynamique le chargement du script de manière asynchrone.

Il existe différentes techniques, mais la plus simple consiste à utiliser document.createElement ("script") lorsque l'événement window.onload est déclenché. Ensuite, le script est chargé en premier lorsque la page elle-même est restituée, ce qui n'a pas d'incidence sur le temps pendant lequel l'utilisateur doit attendre que la page apparaisse.

Cela nécessite naturellement que le script lui-même ne soit pas nécessaire pour le rendu de la page.

Pour plus d'informations, voir l'article Coupling async scripts de Steve Souders (créateur de YSlow mais maintenant sur Google).

1
stpe

L'inclusion de scripts à la fin est principalement utilisée lorsque le contenu/les styles du site Web doivent être affichés en premier.

l'inclusion des scripts dans la tête charge les scripts à l'avance et peut être utilisée avant le chargement de l'ensemble du site Web.

si les scripts sont enfin entrés, la validation n'aura lieu qu'après le chargement de l'ensemble des styles et du design, ce qui n'est pas apprécié par les sites Web rapides.

0
Sanjeev S

Cela dépend, si vous chargez un script qui est nécessaire pour styler votre page/en utilisant des actions dans votre page (comme cliquer sur un bouton), vous feriez mieux de le placer en haut. Si votre style est 100% CSS et que vous avez toutes les options de secours pour les actions des boutons, vous pouvez le placer en bas.

La meilleure chose à faire (si ce n’est pas un problème) est que vous puissiez créer une boîte de chargement modale, placer votre javascript au bas de votre page et le faire disparaître lorsque la dernière ligne de votre script est chargée. De cette manière, vous évitez que les utilisateurs n'utilisent les actions de votre page avant le chargement des scripts. Et aussi éviter le style inapproprié.

0
ahmedmzl
  • Si vous vous souciez toujours beaucoup du support et des performances dans IE <10, il est préférable de TOUJOURS faire en sorte que vos balises de script soient les dernières balises de votre corps HTML. De cette façon, vous êtes certain que le reste du DOM a été chargé et vous ne bloquez pas le rendu.

  • Si vous ne vous souciez plus trop d'IE <10, vous voudrez peut-être placer vos scripts dans l'en-tête de votre document et utiliser defer pour vous assurer qu'ils ne s'exécutent qu'après le chargement de votre DOM (<script type="text/javascript" src="path/to/script1.js" defer></script>). Si vous voulez toujours que votre code fonctionne dans IE <10, n'oubliez pas de l'envelopper dans un window.onload même!

0
user5803163

L'approche moderne en 2019 utilise des scripts de type module ES6.

<script type="module" src="..."></script>

Par défaut, les modules sont chargés de manière asynchrone et différés. c'est-à-dire que vous pouvez les placer n'importe où, ils se chargeront en parallèle et s'exécuteront à la fin du chargement de la page. 

Les différences entre un script et un module sont décrites ici:

https://stackoverflow.com/a/53821485/731548

L'exécution d'un module par rapport à un script est décrite ici:

https://developers.google.com/web/fundamentals/primers/modules#defer

Le support est montré ici:

https://caniuse.com/#feat=es6-module

0
cquezel

Je pense que cela dépend de l'exécution de la page Web. Si la page que vous souhaitez afficher ne peut pas s'afficher correctement sans charger JavaScript, vous devez d'abord inclure le fichier JavaScript. Mais si vous pouvez afficher/rendre une page Web sans télécharger initialement le fichier JavaScript, vous devez alors placer le code JavaScript au bas de la page. Parce qu'il imitera un chargement de page rapide, et du point de vue de l'utilisateur, il semblerait que la page se charge plus rapidement. 

0
Amit Mhaske

Le script bloque le chargement DOM jusqu'à son chargement et son exécution.

Si vous placez des scripts à la fin de <body>, tous les DOM ont la possibilité de charger et de rendre (la page "s'affichera" plus rapidement). <script> aura accès à tous ces éléments DOM.

D'autre part, le placer après <body> start ou supérieur exécutera le script (où il n'y a toujours aucun élément DOM).

Vous incluez jQuery, ce qui signifie que vous pouvez le placer où vous voulez et utiliser .ready ()

0
Szymon Toda

Vous pouvez placer la plupart des références <script> à la fin de <body>,
Mais s'il y a des composants actifs sur votre page qui utilisent des scripts externes,
alors leur dépendance (fichiers js) devrait précéder celle (idéalement dans la balise head).

0
Tech AG

À la fin du document HTML

Pour que cela n'affecte pas le chargement du document HTML dans le navigateur au moment de son exécution.

0
Mr_Blue

Le meilleur endroit pour mettre la balise <script> avant de fermer la balise </body>, de sorte que son téléchargement et son exécution ne bloque pas le navigateur pour analyser le code HTML dans le document,

De plus , le chargement externe des fichiers js a ses propres avantages car il sera mis en cache par les navigateurs et peut réduire le temps de chargement des pages , il sépare le code HTML et le code JavaScript et aident à mieux gérer la base de code .

mais les navigateurs modernes prennent également en charge d'autres méthodes optimales telles que async et defer pour charger des fichiers externes javascript.

Async et différer

Normalement, l’exécution de la page HTML commence ligne par ligne. Lorsqu'un élément JavaScript externe est rencontré, l'analyse HTML est arrêtée jusqu'à ce qu'un fichier JavaScript soit téléchargé et prêt à être exécuté. Cette exécution normale de la page peut être modifiée à l'aide de l'attribut defer et async.

Defer

Lorsqu'un attribut de report est utilisé, JavaScript est téléchargé parallèlement à l'analyse HTML, mais il ne sera exécuté qu'une fois l'analyse HTML complète terminée.

<script src="/local-js-path/myScript.js" defer></script>

Async

Lorsque l'attribut async est utilisé, le code JavaScript est téléchargé dès que le script est rencontré et, après le téléchargement, il est exécuté de manière asynchrone (en parallèle) avec l'analyse HTML.

<script src="/local-js-path/myScript.js" async></script>

Quand utiliser quels attributs

  • Si votre script est indépendant des autres scripts et qu'il est modulaire, utilisez async.
  • Si vous chargez script1 et script2 avec async, les deux s'exécutent.
    parallèlement à l'analyse HTML, dès leur téléchargement
    et disponible.
  • Si votre script dépend d'un autre script, utilisez defer pour les deux:
  • Lorsque Script1 et Script2 sont chargés dans cet ordre avec defer, l'exécution de script1 en premier est garantie.
  • Ensuite, script2 sera exécuté après l'exécution complète de script1.
  • Ceci doit être fait si script2 dépend de script1.
  • Si votre script est suffisamment petit et dépend d'un autre script de type async, utilisez-le sans attributs et placez-le au-dessus de tous les scripts async.

référence: knowledgehills.com

0
Haritsinh Gohil