Is there any advantage to add 'defer' to a new script tag after $(document).ready()?
Asked Answered
K

3

4

I have some javascript that is not required for my initial page load. I need to load it based on some condition that will be evaluated client-side.

$(document).ready(function() {
  let someCondition = true; // someCondition is dynamic
  if (someCondition) {
    var element = document.createElement('script');
    element.src = 'https://raw.githubusercontent.com/Useless-Garbage-Institute/useless-garbage/master/index.js';
    element.defer = true; // does this make a difference?
    element.onload = function() {
      // do some library dependent stuff here
      document.getElementById("loading").textContent = "Loaded";
    };
    document.body.appendChild(element);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="loading">Loading...</h1>

Does it make a difference (in terms of how browser will treat the script tag), if a new tag created using javascript, after document is ready, has 'defer' attribute or not? I think there is no difference, but how can I say for sure?

I believe I understand how deferred scripts behave when script tag is part of the initial html (as described here). Also, this question is not about whether element.defer=true can be used or not (subject of this question).

Kuntz answered 6/9, 2022 at 8:12 Comment(2)
"A script that will be downloaded in parallel to parsing the page, and executed after the page has finished parsing" That's all the defer does.Encyclopedic
In the example i quoted, script tag is attached after dom ready - which is after the page has finished parsing. Does that mean adding defer has no effect here? - It would behave the same as a normal script tag. Parsing and evaluation of the script will block the main thread. - Is that correct?Kuntz
H
5

No that doesn't make any difference, the defer attribute is ignored in case of "non-parser-inserted" scripts:

<script defer src="data:text/javascript,console.log('inline defer')"></script>
<script>
  const script = document.createElement("script");
  script.src = "data:text/javascript,console.log('dynamic defer')";
  script.defer = true;
  document.body.append(script);
</script>
<!-- force delaying of parsing -->
<script src="https://deelay.me/5000/https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Look at your browser's console or pay attention to the logs timestamps to see that the dynamically inserted script actually did execute while we were waiting for the delayed script to be fetched.

Hoyle answered 6/9, 2022 at 9:4 Comment(3)
I unfortunately lack the time right now to review the specs thoroughly but I believe it's managed in prepare the script element, step 31.3 which checks if script is not parser inserted before checking the defer attribute.Hoyle
Thanks Kaiido. What about the async attribute - is it also useless for a dynamically-added script?Occlude
@Occlude yes it's also useless. Scripts that aren't "parser-inserted" are async.Hoyle
R
0

There's a difference between adding them to the function and adding directly the CDN ( especially in your case ).

Let's look at the code execution of the above-mentioned code first,

  1. You have added the jquery CDN first ( without defer ) so that loads first.
  2. $(document).ready will be fired once after the complete load of jquery.
  3. There'll be the creation and insertion of a new script tag to the dom.
  4. Download the https://raw.githubusercontent.com/Useless-Garbage-Institute/useless-garbage/master/index.js asynchronously.

Let's look at another approach: adding CDN to the code:

  1. Your DOM will have 2 script tags.
  2. Both will start loading based on the type of load parallelly ( defer async etc ).
  3. Notice you are not waiting for the dom ready event to load the second script.

I suggest adding only the main JS part in a js file and adding it to the CDN. Others can wait load with the delay. In case you are really needed with a js src, then don't load it the first way since it waits for the complete page load.

I suggest you read and look at web-vitals and SEO for this.

and for your other question, yes you can add defer attribute with element.defer=true to the elements while creating and loading to DOM.

Hope this answer helps you! Feel free to comment if you get any errors or doubts.

Reverberator answered 6/9, 2022 at 8:46 Comment(0)
S
-1

I think the JQuery Arrive lib will solve your case.

Stander answered 6/9, 2022 at 8:33 Comment(5)
How does this help?Diluvium
@Diluvium Use arrive to check the condition, for example a specific element is visible. Then append the script tag into to html.Stander
That doesn't answer the question of "what does the refer attribute do".Diluvium
The problem is some javascript that is not required for my initial page load so we can solve it in that way.Stander
Oh I see. May you add an example then? A link only answer is rarely helpfulDiluvium

© 2022 - 2024 — McMap. All rights reserved.