web-dev-qa-db-fra.com

Balise de script - asynchrone et différée

J'ai quelques questions sur les attributs async & defer de la balise <script> qui, à ma connaissance, ne fonctionnent que dans les navigateurs HTML5.

L'un de mes sites contient deux fichiers JavaScript externes qui se trouvent actuellement juste au-dessus de la balise </body>. le premier est jquery provient de Google et le second est un script externe local.

En ce qui concerne la vitesse de chargement du site

  1. Y at-il un avantage à ajouter async aux deux scripts que j’ai au bas de la page?

  2. Y aurait-il un avantage à ajouter l'option async aux deux scripts et à les placer en haut de la page dans le <head>?

  3. Cela signifie-t-il qu'ils se téléchargent au chargement de la page?
  4. Je suppose que cela provoquerait des retards pour les navigateurs HTML4, mais est-ce que cela accélérerait le chargement des pages pour les navigateurs HTML5?

Utiliser <script defer src=...

  1. Le chargement des deux scripts dans <head> avec l'attribut defer aurait-il le même effet que d'avoir les scripts avant </body>?
  2. Une fois encore, je suppose que cela ralentirait les navigateurs HTML4.

Utiliser <script async src=...

Si j'ai deux scripts avec async activé

  1. Est-ce qu'ils téléchargeraient en même temps?
  2. Ou un à la fois avec le reste de la page?
  3. Est-ce que l'ordre des scripts devient alors un problème? Par exemple, un script dépend de l'autre, donc si l'un télécharge plus rapidement, le second risque de ne pas s'exécuter correctement, etc.

Enfin, est-il préférable de laisser les choses en l'état jusqu'à ce que HTML5 soit plus couramment utilisé?

422
Adam

Gardez vos scripts juste avant </body>. Async peut être utilisé avec des scripts situés dans certaines circonstances (voir la discussion ci-dessous). Différer ne fera pas beaucoup de différence pour les scripts qui s'y trouvent car le travail d'analyse DOM a déjà été effectué de toute façon.

Voici un article qui explique la différence entre asynchrone et différé: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ .

Votre code HTML s’affichera plus rapidement dans les anciens navigateurs si vous conservez les scripts à la fin du corps juste avant </body>. Donc, pour préserver la vitesse de chargement dans les navigateurs plus anciens, vous ne voulez pas les placer ailleurs.

Si votre deuxième script dépend du premier script (par exemple, votre deuxième script utilise le jQuery chargé dans le premier script), vous ne pouvez pas les rendre asynchrones sans code supplémentaire pour contrôler l'ordre d'exécution, mais vous pouvez les différer, car les scripts différés toujours être exécuté dans l’ordre, mais seulement après que le document a été analysé. Si vous avez ce code et que vous n'avez pas besoin que les scripts s'exécutent immédiatement, vous pouvez les rendre asynchrones ou différés.

Vous pouvez placer les scripts dans la balise <head> et les définir sur defer. Le chargement des scripts sera différé jusqu'à ce que le DOM soit analysé, ce qui permettra un affichage rapide de la page dans les nouveaux navigateurs prenant en charge le différé. , mais cela ne vous aidera pas du tout dans les anciens navigateurs et ce n’est pas vraiment plus rapide que de simplement mettre les scripts juste avant </body> qui fonctionne dans tous les navigateurs. Vous pouvez donc voir pourquoi il est préférable de les mettre juste avant </body>.

Async est plus utile lorsque vous ne vous souciez pas du chargement du script et que rien d'autre qui dépend de l'utilisateur ne dépend de son chargement. L'exemple le plus souvent cité pour l'utilisation asynchrone est un script analytique tel que Google Analytics que vous ne voulez rien attendre et qu'il n'est pas urgent de lancer rapidement et qu'il est autonome et que rien d'autre n'en dépend.

Habituellement, la bibliothèque jQuery n'est pas un bon candidat pour asynchrone car d'autres scripts en dépendent et vous souhaitez installer des gestionnaires d'événement pour que votre page puisse commencer à répondre aux événements utilisateur et vous devrez peut-être exécuter un code d'initialisation basé sur jQuery pour établir l'état initial. de la page. Il peut être utilisé en mode asynchrone, mais d'autres scripts devront être codés pour ne pas s'exécuter avant le chargement de jQuery.

354
jfriend00

Cette image explique les balises de script normales, asynchrones et différées.

enter image description here

  • Les scripts asynchrones sont exécutés dès le chargement du script, ce qui ne garantit pas l'ordre d'exécution (un script que vous avez inclus à la fin peut être exécuté avant le premier fichier de script).

  • Les scripts différés garantissent l'ordre d'exécution dans lequel ils apparaissent dans la page.

Référez-vous à ce lien: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

632
Prasanth Bendra

HTML5: async, defer

En HTML5, vous pouvez indiquer au navigateur quand exécuter votre code JavaScript. Il y a 3 possibilités:

<script       src="myscript.js"></script>

<script async src="myscript.js"></script>

<script defer src="myscript.js"></script>
  1. Sans async ou defer, le navigateur exécutera votre script immédiatement, avant de restituer les éléments situés sous la balise de script.

  2. Avec async (asynchrone), le navigateur continuera à charger la page HTML et à le rendre pendant le chargement et l’exécution du script en même temps.

  3. Avec defer, le navigateur exécutera votre script une fois l'analyse de la page terminée. (Il n'est pas nécessaire de terminer le téléchargement de tous les fichiers image. C'est bien.)

197
Dinesh

Les scripts async et defer commencent à se télécharger immédiatement sans mettre l'analyseur en pause. Ils prennent également en charge un gestionnaire facultatif onload pour répondre à la nécessité courante d'initialisation qui dépend du script.

La différence entre async et defer est centrée autour de l'exécution du script. Chaque script async s’exécute à la première occasion, une fois le téléchargement terminé et avant le chargement de la fenêtre. Cela signifie qu'il est possible (et probable) que les scripts async ne soient pas exécutés dans l'ordre dans lequel ils apparaissent dans la page. Alors que les scripts defer, en revanche, sont garantis pour être exécutés dans l'ordre dans lequel ils apparaissent dans la page. Cette exécution commence une fois l’analyse terminée, mais avant l’événement DOMContentLoaded du document.

Source & autres détails: ici .

25
Zameer Khan

Face au même genre de problème et maintenant clairement compris comment les deux vont fonctionner. Espérons que ce lien de référence sera utile ...

Async

Lorsque vous ajoutez l'attribut asynchrone à votre balise de script, voici ce qui se passe.

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Faites des demandes parallèles pour récupérer les fichiers.
  2. Continuez à analyser le document comme s’il n’était jamais interrompu.
  3. Exécutez les scripts individuels au moment du téléchargement des fichiers.

Diffère

Defer est très similaire à async avec une différence majeure. Voici ce qui se passe lorsqu'un navigateur rencontre un script avec l'attribut de report.

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Faites des demandes parallèles pour récupérer les fichiers individuels.
  2. Continuez à analyser le document comme s’il n’était jamais interrompu.
  3. Terminez l'analyse du document même si les fichiers de script ont été téléchargés.
  4. Exécutez chaque script dans l'ordre dans lequel ils ont été rencontrés dans le document.

Référence: Différence entre asynchrone et différé

22
kamesh

Il semble que le comportement de différer et d’async dépend du navigateur, du moins de la phase d’exécution. REMARQUE, différer s'applique uniquement aux scripts externes. Je suppose qu'async suit le même schéma.

Dans IE 11 et ci-dessous, l'ordre semble être le suivant:

  • async (peut s'exécuter partiellement pendant le chargement de la page)
  • none (peut s'exécuter pendant le chargement de la page)
  • différer (s'exécute après la page chargée, tout différer dans l'ordre de placement dans le fichier)

Dans Edge, Webkit, etc., l'attribut async semble ignoré ou placé à la fin:

  • data-pagespeed-no-defer (s'exécute avant tout autre script pendant le chargement de la page)
  • none (peut s'exécuter pendant le chargement de la page)
  • différer (attend que DOM soit chargé, différer dans l'ordre de placement dans le fichier)
  • async (semble attendre que DOM soit chargé)

Dans les nouveaux navigateurs, l'attribut data-pagespeed-no-defer est exécuté avant tout autre script externe. Ceci est pour les scripts qui ne dépendent pas du DOM.

REMARQUE: utilisez différer lorsque vous avez besoin d'un ordre d'exécution explicite de vos scripts externes. Cela indique au navigateur d’exécuter tous les scripts différés par ordre de placement dans le fichier.

ASIDE: La taille des javascripts externes importait vraiment lors du chargement ... mais n'avait aucun effet sur l'ordre d'exécution.

Si les performances de vos scripts vous inquiètent, vous pouvez envisager une minification ou simplement les charger de manière dynamique avec XMLHttpRequest.

1
Charles Owen

Je pense que Jake Archibald nous a présenté quelques idées en 2013 qui pourraient ajouter encore plus de potentiel au sujet:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

Le Saint-Graal a un ensemble de scripts à télécharger immédiatement sans bloquer le rendu et s'exécuter dès que possible dans l'ordre dans lequel ils ont été ajoutés. Malheureusement, HTML vous déteste et ne vous laissera pas faire cela.

(...)

La réponse est en fait dans la spécification HTML5, bien qu’elle soit cachée au bas de la section de chargement de script. " L'attribut IDL asynchrone détermine si l'élément doit s'exécuter de manière asynchrone ou non. Si l'indicateur" force-async "de l'élément est défini, l'attribut IDL asynchrone doit être true et, lors de l'obtention, à true , le drapeau "force-asynchrone" doit d'abord être désactivé ... ".

(...)

Les scripts créés et ajoutés dynamiquement au document sont asynchrones par défaut , ils ne bloquent pas le rendu et s'exécutent dès leur téléchargement, ce qui signifie qu'ils pourraient sortir dans le mauvais ordre. Cependant, nous pouvons les marquer explicitement comme non asynchrones:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

Cela confère à nos scripts un mélange de comportements impossible à obtenir avec du HTML simple. En étant explicitement non asynchrones, les scripts sont ajoutés à une file d’exécution, la même file qu’ils ont été ajoutés à notre premier exemple en langage HTML brut. Toutefois, en raison de leur création dynamique, ils sont exécutés en dehors de l'analyse du document. Le rendu n'est donc pas bloqué tant qu'il est téléchargé (ne confondez pas le chargement de script non asynchrone avec sync XHR, ce qui n'est jamais une bonne chose).

Le script ci-dessus doit être inclus en ligne dans l'en-tête des pages, mettre en file d'attente les téléchargements de script dès que possible sans perturber le rendu progressif, et s'exécuter dès que possible dans l'ordre que vous avez spécifié. "2.js" est gratuit à télécharger avant "1.js", mais il ne sera exécuté que si "1.js" a été téléchargé et exécuté avec succès ou n’a pas réussi à le faire. Hourra! async-download mais ordonné-execution !

Pour autant, ce n'est peut-être pas le moyen le plus rapide de charger des scripts:

(...) Avec l'exemple ci-dessus, le navigateur doit analyser et exécuter un script pour déterminer les scripts à télécharger. Cela masque vos scripts des scanners de préchargement. Les navigateurs utilisent ces scanners pour découvrir des ressources sur les pages que vous êtes susceptibles de visiter, ou pour découvrir des ressources de page alors que l’analyseur est bloqué par une autre ressource.

Nous pouvons rajouter de la découvrabilité en mettant cela dans la tête du document:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

Cela indique au navigateur que la page a besoin de 1.js et 2.js. link [rel = sous-ressource] est similaire à link [rel = prefetch], mais avec une sémantique différente. Malheureusement, il n’est actuellement pris en charge que par Chrome et vous devez déclarer les scripts à charger deux fois, une fois via des éléments de lien et une autre fois dans votre script.

Correction: Au départ, j'avais déclaré que ces fichiers avaient été récupérés par le scanner de précharge, mais pas par l'analyseur syntaxique standard. Cependant, le scanner de préchargement pourrait les détecter, mais pas encore, alors que les scripts inclus dans le code exécutable ne peuvent jamais être préchargés. Merci à Yoav Weiss qui m'a corrigé dans les commentaires.

0
mjfneto