J'ai le code HTML suivant:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/blazy/1.8.2/blazy.min.js" defer></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.9.0/js/lightbox.min.js" defer></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous" defer></script>
<!-- 26 dec flexslider js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/flexslider/2.6.3/jquery.flexslider.min.js" defer></script>
<script defer>
(function($) {
$(document).ready(function() {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
});
})(jQuery);
</script>
</head>
<body>
</body>
</html>
Je reçois une erreur en disant que jQuery n'est pas défini. Maintenant, même si je supprime différer de mon code JS en ligne, cela signifie que jQuery n’est pas défini. Pour une raison quelconque, je dois garder les plugins jQuery dans la tête et garder mon code JS en ligne. Ma question est:
Pourquoi le code Javascript en ligne n'est-il pas différé lorsque l'attribut defer
est présent?
Existe-t-il un moyen d’imiter le comportement différé sur mon code Javascript intégré? Je peux mettre cela à la fin de la balise body si nécessaire.
Les scripts avec l'attribut defer
se chargent dans l'ordre dans lequel ils ont été spécifiés, mais pas avant le document lui-même a été chargé. Comme defer
n'a aucun effet sur les balises script
, à moins qu'elles aient également l'attribut src
, le premier script exécuté est votre script inline. Donc, à ce moment-là, jQuery n'est pas encore chargé.
Vous pouvez résoudre ce problème d'au moins deux manières:
Mettez votre script en ligne dans un fichier .js
Et faites-le référence avec un attribut src
(en plus de l'attribut defer
que vous aviez déjà là), ou
Laissez votre script en ligne attendre que le document et les scripts différés soient chargés. L'événement DOMContentLoaded
se déclenchera à ce moment-là:
<script>
window.addEventListener('DOMContentLoaded', function() {
(function($) {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
})(jQuery);
});
</script>
NB: Notez que dans ce dernier cas, $(document).ready(function()
n'est plus inclus car cela attendrait le même événement (DOMContentLoaded
). Vous pourriez l'inclure comme vous l'aviez dans votre code d'origine, mais jQuery exécuterait simplement le rappel immédiatement, ce qui ne fait aucune différence pratique.
Vous pouvez créer une URL Base64 à partir du script et la placer dans le fichier src!
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer>
</script>
J'ai construit un test rapide pour le voir en action. Vous devriez voir une alerte avec Hello world!
dernier si defer
fonctionne:
<script defer>
alert('Why no defer?!?');
</script>
<!-- alert('Hello world!'); -->
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer></script>
<script>
alert('Buh-bye world!');
</script>
Le faire manuellement est un peu laborieux, donc si vous avez le luxe de compiler votre code HTML de quelque manière que ce soit (guidon, angulaire, etc.), cela vous sera très utile.
J'utilise actuellement:
<script src="data:text/javascript;base64,{{base64 "alert('Hello world!');"}}"
defer>
</script>
De la documentation MDN:
différé
Cet attribut booléen est défini pour indiquer à un navigateur que le script doit être exécuté après l'analyse du document, mais avant le lancement deDOMContentLoaded
. L'attribut de report ne doit être utilisé que sur des scripts externes.
Ceci s'appelle un IIFE (expression de fonction immédiatement appelée) qui est exécuté avant que DOM ne soit disponible. Donc, dans ce cas, jQuery
n'est pas défini car ce n'est pas dans le DOM.
#noLib #vanillaJS
suggère de ne pas utiliser la production de plusieurs navigateurs
jusqu'à ce que MS IE meurt et MS Edge adopte l'open source Chromium;)
spec script # attr-defer (documents Web MDN) : "Cet attribut ne doit pas être utilisé si l'attribut src est absent (c'est-à-dire pour les scripts intégrés), dans ce cas, cela n'aurait aucun effet."
spec Data_URI
avec right tapez "text/javascript" il n’est pas nécessaire de base64 du tout... ;)
en utilisant du texte brut afin que vous puissiez utiliser simple:
<script defer src="data:text/javascript,
//do something with b-lazy plugin, lightbox plugin and then with flexslider
lightbox.option({
resizeDuration: 200,
wrapAround: true
})
">
oui, c'est un peu bizarre bidouille, mais <script type="module">
sont différés par défaut, il n’ya pas d’autre option pour mélanger dans l’ordre exact :
Il est de notoriété publique que vous devriez utiliser <script src=".." async defer>
(ou définissez script.async = true
avant d’attribuer src
, lorsque vous le faites à partir de JS) et/ou de placer vos scripts au bas de la page, afin que la plus grande partie possible de la page soit chargée et restituée à l'utilisateur, aussi vite que possible.
defer.js (note: Je suis l'auteur de ce script ) est écrit en JavaScript, ce qui rend le chargement paresseux impossible contenu plus rapide et performant. Vous pouvez différer efficacement les fichiers javascript et les blocs de script intégrés.
Si votre page est juste une page HTML améliorée avec du JavaScript, alors vous êtes bon avec seulement <script async>
. Il faut du temps au navigateur pour analyser et exécuter ces scripts, et chaque modification de l'interface utilisateur peut redistribuer votre mise en page, ralentir la vitesse de chargement, personne n'aime regarder une page blanche vierge; les utilisateurs sont impatients et partiront rapidement.
Dans divers cas, utiliser async
ou defer
ne permet pas d'obtenir une vitesse de page plus rapide que celle de defer.js .