web-dev-qa-db-fra.com

Comment différer Javascript en ligne?

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:

  1. Pourquoi le code Javascript en ligne n'est-il pas différé lorsque l'attribut defer est présent?

  2. 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.

39
user31782

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.

77
trincot

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>
36
Brook Jordan

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 de DOMContentLoaded. 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.

5
Jai

reporter le chargement avec l'URI des données en texte brut - Chrome et FF

#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;)

le seul moyen de différer le script est un fichier externe ou Data_URI (sans utiliser événement DOMContentLoaded)

reporter

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."

Data_URI

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 :

  • module de fichiers externes - différé par défaut
  • scripts intégrés au module - différé par défaut
  • fichiers externes - éventuellement différés
  • scripts en ligne - seulement avec ce hack - comme je le sais (sans bibliothèques ni frameworks)
1

Les balises de script différées/asynchrones ne suffisent pas

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.

Defer loading of JavaScript

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 .

1
shinsenter