defer scripts and execution order on browsers
Asked Answered
A

3

31

I have been working on adding defer attribute for external scripts used in HEAD section of one of my projects. I had a query on execution order of multiple defer'ed script tags.

Below are my observation which will help us understand my query better:

As per http://www.w3.org/TR/html5/scripting-1.html

the defer attribute is present, then the script is executed when the page has finished parsing

The defer attribute does work. But, I am doubtful on the execution order. It looks like it is different on FF and Chrome.

As per my porject:

<script defer="defer" src="{SERVER_PATH}/deps.js?1441452359"></script>
<script defer="defer" src="{SERVER_PATH}/script1.js?1440067073"></script>
<script defer="defer" src="{SERVER_PATH}/script2.js?1441451916"></script>

Here, deps.js is huge file of around 120kb (gzipped), whereas, script1-3 are of regular size of 20-50kb (gzipped).

On Firefox, execution of defer'ed script does start in order of appearance, but doesn't complete in the same order. Where'as, on chrome unless the previous script completes execution, the next script's execution doesn't start. It looks like Chrome makes sense.

To test the execution order, I had inserted console.log at the first and last line of each scripts, for e.g. in deps.js

console.log("Execution Start: deps");
// minified deps script content.
console.log("Execution End: deps");

Below the console output on Firefox:

Execution Start: deps
Execution Start: script1
Execution Start: script2
// Script Error as script1 needs deps to render completely.
// Script Error as script2 needs deps to render completely.
Execution End: deps

Below the console output on Chrome:

Execution Start: deps
Execution End: deps
Execution Start: script1
Execution End: script1
Execution Start: script2
Execution End: script2

However, behavior on FF is not always as shown above. Sometimes it does work like Chrome. It look like an issue which is Firefox only. Or, may be is it because of the deps.js file being heavy and minified and takes time to render.

Can anyone of similar experience with defer help me? Please let me know, if any other information is needed.

PS: Other solutions like, moving the scripts at the bottom of the page is not something I am looking at this moment.

Artur answered 5/9, 2015 at 12:54 Comment(13)
When you defer files, they are guaranteed (if properly implemented in browser) to execute in order they appear on the element. My favorite explanation of the issue: growingwiththeweb.com/2014/02/async-vs-defer-attributes.htmlStorey
@NinoŠkopac I agree with you. They should execute in the order. But FF seems to behave differenty sometimes, the execution start order is same, but execution end order is not same. The same implementation works fine on Chrome. Odd.Artur
are you using the latest version of FF?Storey
@NinoŠkopac Yes. 40.0.3Artur
That's weird, but in the same time, even the latest stable version of Chrome (v. 45) is bugging out when using Google pages. Take a look at this: github.com/PolymerLabs/bowerzipper/issues/…Storey
@NinoŠkopac thats my first doubt, may be the latest version of FF might be buggy.Artur
What happens when you run the second test on this page: contentloaded.com/async-defer (in FF and an older version of FF)? Does it print A B C in wrong order?Pretoria
@SalmanA It does print ABC in order. But, I am not sure if the A B C files are of different file size, one being of higher file size.Artur
@BijoyAnupam all three scripts are delayed by different amount of time to simulate out-of-order download.Pretoria
I have been seeing this issue in Firefox 42.0.1 on Android, and came across this Mozilla bug report: bugzilla.mozilla.org/show_bug.cgi?id=1212696.Doyen
thanks @Doyen Looks like the bug is related to what i observed.Artur
It looks a bit insane, as assuming sync execution, there's no chance that some other scripts start executing before one that already started ended. If it's the case it will mean that FF does some multi-threading which by all means should not take place. Can you confirm that your start and end logs are scheduled to work in very same event loop?Wicklow
This question is incomplete as it doesn't mention IE! :pAssault
H
13

HTML5.0 spec says this:

If the element has a src attribute, and the element has a defer attribute, and the element has been flagged as "parser-inserted", and the element does not have an async attribute

The element must be added to the end of the list of scripts that will execute when the document has finished parsing associated with the Document of the parser that created the element.

The task that the networking task source places on the task queue once the fetching algorithm has completed must set the element's "ready to be parser-executed" flag. The parser will handle executing the script.

So it does say it defers script execution until the associated Document is parsed, it also says it's pushed into the list. So the order of the list should be as the script order is being parsed-inserted.

However, the second part kind of worries me. It basically says that it will only be marked for execution until the network task finsihed downloading the script. Then... "parser will handle executing the script".

What I couldn't find in the spec is the case covering script execution after document parsing. Does it keep executing scripts in the list order as they become "ready to be parser-executed"? Or will it wait until all scripts in the list are "ready to be parser executed" then execute them.

Spec (step 15): http://www.w3.org/TR/html5/scripting-1.html#script-processing-src-prepare

Hadwin answered 5/9, 2015 at 13:34 Comment(2)
From that it does sound that they are executed in order. If it waits for all to be downloaded or not might just be implementation defined, and not waiting unless necessary for ordering is likely the better implementation?Dost
I agree that it's most likely the better implementation. When i wrote this answer was just hinting toward possible different behavior between browsers because of how they were executed. Although it most likely wasn't the case.Hadwin
F
4

Deferred scripts keep their relative order, just like regular scripts.

Consider we have a page with 2 scripts in the following order:

<script defer src="/big.js"></script>
<script defer src="/small.js"></script>

Browsers download those 2 scripts in parallel, but run by the order they go on the page. So big.js will be executed first despite of that small.js can be downloaded earlier.

Forsta answered 23/4, 2022 at 20:45 Comment(0)
W
1

I'd say it's not really possible unless "Execution End" log happens in different event loop than "Execution Start" log.

Can you ensure us on that? As otherwise it will mean that Firefix does some multithreading here, and as we know, there's no support in JS for that.

Wicklow answered 9/11, 2016 at 9:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.