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.
Y at-il un avantage à ajouter async
aux deux scripts que j’ai au bas de la page?
Y aurait-il un avantage à ajouter l'option async
aux deux scripts et à les placer en haut de la page dans le <head>
?
<script defer src=...
<head>
avec l'attribut defer
aurait-il le même effet que d'avoir les scripts avant </body>
?<script async src=...
Si j'ai deux scripts avec async
activé
Enfin, est-il préférable de laisser les choses en l'état jusqu'à ce que HTML5 soit plus couramment utilisé?
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.
Cette image explique les balises de script normales, asynchrones et différées.
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
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>
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.
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.
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.)
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 .
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>
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>
Référence: Différence entre asynchrone et différé
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:
Dans Edge, Webkit, etc., l'attribut async semble ignoré ou placé à la fin:
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.
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.