sirve - ¿Cómo diferir Javascript en línea?
title css (3)
De los documentos de MDN:
aplazar
Este atributo booleano se configura para indicar a un navegador que el script debe ejecutarse después de que se haya analizado el documento, pero antes de dispararDOMContentLoaded
. El atributo de aplazamiento solo se debe utilizar en scripts externos.
Esto se denomina IIFE (expresión de función invocada inmediatamente) que se ejecuta antes de que DOM esté disponible. Entonces, en ese caso jQuery
no está definido porque no está en el DOM.
Tengo el siguiente código html:
<!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>
Recibo un error, diciendo que jQuery no está definido. Ahora, incluso si elimino el aplazamiento de mi código JS en línea, dice que jQuery no está definido. Por alguna razón, tengo que mantener los complementos de jQuery en la cabeza y mantener mi código JS en línea. Mi pregunta es:
¿Por qué no se difiere el código Javascript en línea cuando está presente el atributo de aplazamiento?
¿Hay alguna manera de imitar el comportamiento de aplazamiento en mi código Javascript en línea? Puedo poner eso al final de la etiqueta del cuerpo si es necesario.
Los scripts con el atributo de defer
cargan en el orden en que se especifican, pero no antes de que se haya cargado el documento. Como el defer
no tiene efecto en las etiquetas de script
menos que también tengan el atributo src
, el primer script que se ejecuta es su script en línea. Así que en ese momento jQuery no está cargado todavía.
Puedes resolver esto al menos de dos maneras:
Coloque su script en línea en un archivo
.js
y haga referencia a él con un atributosrc
(además del atributo dedefer
que ya tenía allí), oDeje que el script en línea espere a que se carguen el documento y los scripts diferidos. El evento
DOMContentLoaded
se activará cuando eso ocurra:<script> window.addEventListener(''DOMContentLoaded'', function() { (function($) { //do something with b-lazy plugin, lightbox plugin and then with flexslider })(jQuery); }); </script>
NB: Observe que en el último caso $(document).ready(function()
ya no se incluye, ya que eso esperaría el mismo evento ( DOMContentLoaded
). Aún podría incluirlo como lo había hecho en su código original, pero entonces jQuery solo ejecutaría la devolución de llamada inmediatamente , lo que no representa una diferencia práctica.
Puede crear una URL Base64 fuera del script y ponerla en el src!
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer>
</script>
Construí una prueba rápida para verlo en acción. Deberías ver una alerta con Hello world!
último si el defer
está funcionando:
<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>
Hacerlo manualmente es un poco laborioso, por lo que si tiene el lujo de compilar su HTML de alguna manera (manillares, Angular, etc.), eso ayuda mucho.
Actualmente estoy usando:
<script src="data:text/javascript;base64,{{base64 "alert(''Hello world!'');"}}"
defer>
</script>