Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to defer inline Javascript?

I have the following html code:

<!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> 

I get an error, saying jQuery is not defined. Now even if I remove defer from my inline JS code, it says jQuery is undefined. For some reason I have to keep the jQuery plugins in the head and keep my JS code inline. My question is:

  1. Why doesn't inline Javascript code get deferred when defer attribute is present on it?

  2. Is there a way to imitate the defer behavior on my inline Javascript code? I can put that at the end of body tag if required.

like image 623
user31782 Avatar asked Dec 30 '16 10:12

user31782


People also ask

Can you defer inline JavaScript?

Inline JavaScript executes in the order in which it appears in the page. There's no “deferring” it. As a result, if something in there relies on jQuery, it'll simply throw an error to the console log and refuse to execute.

How do you defer in JavaScript?

Definition and UsageIf the defer attribute is set, it specifies that the script is downloaded in parallel to parsing the page, and executed after the page has finished parsing. Note: The defer attribute is only for external scripts (should only be used if the src attribute is present).

How do I stop an inline script?

The term "in line" is not defined in a standard anywhere, it's jargon that typically refers to adding script in an element attribute like <button onclick="someFun(this)" ...> . It is avoided by adding script dynamically as you're doing, which is usually done in the head or just before the closing body tag.

Should I use defer in JavaScript?

You should use defer for all other scripts. defer is great because it: Gets loaded as soon as possible — so it reduces load times. Doesn't execute until everything you need is ready — so all the DOM you need is there.


2 Answers

The scripts with the defer attribute load in the order they are specified, but not before the document itself has been loaded. As defer has no effect on script tags unless they also have the src attribute, the first script that gets executed is your inline script. So at that time jQuery is not loaded yet.

You can solve this in at least two ways:

  • Put your inline script in a .js file and reference it with a src attribute (in addition to the defer attribute which you already had there), or

  • Let your inline script wait for the document and the deferred scripts to be loaded. The DOMContentLoaded event will fire when that has happened:

    <script>     window.addEventListener('DOMContentLoaded', function() {         (function($) {             //do something with b-lazy plugin, lightbox plugin and then with flexslider         })(jQuery);     }); </script> 

NB: Notice that in the latter case $(document).ready(function() is not included any more, as that would wait for the same event (DOMContentLoaded). You could still include it like you had in your original code, but then jQuery would just execute the callback immediately, which makes no practical difference.

like image 192
trincot Avatar answered Sep 27 '22 17:09

trincot


You can create a Base64 URL out of the script and put it into the src!

<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="         defer> </script> 

I built a quick test to see it in action. You should see an alert with Hello world! last if defer is working:

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

Doing it manually is a little laborious so if you have the luxury of compiling your HTML in some way (Handlebars, Angular, etc.) then that helps a lot.

I'm currently using:

<script src="data:text/javascript;base64,{{base64 "alert('Hello world!');"}}"         defer> </script> 
like image 22
Brook Jordan Avatar answered Sep 27 '22 19:09

Brook Jordan