Richard said:
Jeremy J Starcher wrote :
Can you point to these tests, as I do not believe that they would show
any such thing except by coincidence?
Some of the tests I've seen can be found on steve's site. Here are some
others:-
http://stevesouders.com/efws/links.php?ex
We do know that requesting an external script resource will block the
HTML parser. It has to because there is always the possibility (in the
absence of the DEFER attribute) that such a script will perform a -
document.write - and so insert character sequences into the HTML
parser's input (which has to happen immediately following the closing
script tag for the importing element else chaos will ensue). This does
not necessitate blocking IO.
A script may have ASYNC or DEFER, allowing the script to be loaded at a
later time.
From HTML 4.01:-
| If the src has a URI value, user agents must ignore the element's
| contents and retrieve the script via the URI.
But when and how? HTML 4.01 does not define load order.
A browser could follow the standard, and when parsing a script with the
absence of DEFER and ASYNC, load it asynchronously. That is sort of a
technical "loophole" that, if implemented, would break a lot sites.
We can look at what browsers do. When a browser parses a script tag with
a SRC and no ASYNC/DEFER, it interprets a script, downloading it first,
if necessary. The interpretation blocks subsequent rendering of the page
and reading the file from the network (or local cache) blocks
interpretation. This is a "de facto" standard where browsers will block
on some resources, and they do this because a script may include a meta
refresh, document.write, location.replace, or other content that is
expected to be run synchronously.
Browsers follow a "chain of responsibility".
Consider this scenario; The browser is going to follow the HTTP
restrictions and limit the number of simultaneous HTTP connections to 2,
That is not a restriction, but for the sake of example, we can assume that.
but the HTML parser is working form a buffer into which the HTML has
been loaded having completed being downloaded so both connections are
available. The parser encounters a LINK to an external style sheet so it
starts to use one connection to download the style sheet. It could do
that asynchronously, so lets assume that it does. It then encounters a
SCRIPT element calling for an external resource, so it starts to
download that with the second HTTP connection. This may force it to
block the HTML parser, but if it has not finished downloading the style
Really? Why can't browser eagerly parse to look ahead?
If the browser has not finished downloading the LINK'd stylesheet, it
may opt to not interpret the script. Firefox chooses this option. If the
browser does not perform an eager download of the script, it will wait
for the stylesheet to be interpreted and applied (and that depends on
the stylesheet to be downloaded) before the script will be requested.
So, a LINK can effectively block a script.
In Firefox <= 3.1, a script that follows a LINK'd styleSheet will not
load until the stylesheet loads.
sheet, there is no reason in the world why it should do anything to
interrupt that process.
Blocking all subsequent elements from loading. There is no reason to
believe that they would block previous elements for which resources
could be downloaded asynchronously, such as style sheets or image data.
And the fact that scripts will have to be downloaded in tern (or at
least handled in turn by the client) suggests that only one connection
needs to be devoted to that task, leaving the other free for those other
resources to be retrieved in parallel.
Again, in Firefox <= 3.1, a script that follows a stylesheet will not
load until the stylesheet loads.
It is not necessary to download scripts in series to interpret those
scripts in series. If the browser has a script in the HTML parser's
buffer, it can download that resource.
For stylesheets in the HEAD, browsers will wait for the stylesheet to be
interpreted before rendering the document. This means a LINK can
effectively be another "blocking resource".
Using - document.write - really should not do that, and I would be
massively suspicious of any evidence that it does.
SCRIPTs included via document.write evaluate in order. This is not an
official standard, but a "de facto" standard. When a script writes a
script, as in:-
<script>
var a, b;
document.write("<script src="a.js"><\/script>");
document.write("<script src="b.js"><\/script>");
</script>
<script>document.write("a=" + a, "b="+b);
- the script being written is inserted into the document after the
closing script tag where document.write was called.
The dynamically added scripts may be downloaded at any time before they
are interpreted. They may be downloaded prior to being added to the
document, or they may be cached. When the browser encounters the
</script>, the document.written HTML (SCRIPTs) is included and the
scripts that were included via document.write will be interpreted in order.
An HTTP request for a script and the execution of that script are two
completely different actions. It is not necessary to couple these.
To test if this happens, we try including the scripts in various ways,
either by direct include, document.write, or dynamic insertion, and not
usind ASYNC or DEFER.
Each technique can be used on three scripts, effecting a delay on the
second. The delay is created by server processing (Thread.sleep does
it). The scripts should execute serially, but can be requested
asynchronously.
Test Approach:
The server-generated script outputs a "time request received" for each
script. Subtract the third "time requested" from the second. If the time
difference is less than the programmed delay, then the browser made a
predictive fetch of the script resource.
No standard nails down load order, so there is no guarantee of any result.
That using - document.wirte - results in asynchronous script downloading?
While I would be suspicious anyone writing/talking on this subject who
did not publish there full methodology, resulting data and the reasoning
behind the conclusions that they drew from it. Browser scripting is
already plagued with far too many mystical incantations and cargo-cults
for anyone to start jumping through new hoops before seeing some
scientific method backing up the need to do so.
I'm looking at the video and Example 4, aka "The Best One":-
var domscript = document.createElement('script');
domscript.src = "menu.js";
domscript.onloadDone = false;
domscript.onload = function() {
domscript.onloadDone = true;
init();
};
domscript.onreadystatechange = function() {
if ( "loaded" === domscript.readyState &&
! domscript.onloadDone ) {
domscript.onloadDone = true;
init();
}
}
document.getElementsByTagName("head")[0].appendChild(domscript);
- and wondering: Is there a circular reference to watch out for between
the script and the function? e.g. I see no:-
script.onreadystatechange = domscript.onload = null;
- after init.
Is there a race condition here, too? Could
|domscript.onreadystatechange| become "loaded" before
|domscript.onload|? Ouch. Method init() is called twice, with different
conditions in each.
Why not use a variable instead of |domscript.onloadDone|? I can't see
justification for that expando, when it would be safer and easier to write:-
var isDomScriptLoaded = false, or something like that. Expandos are easy
to avoid.
Please see the "cuzillion" site for more.
http://stevesouders.com/cuzillion/
http://stevesouders.com/cuzillion/help.php#examples
Quirks mode can affect the outcome of the tests. Also:
http://stevesouders.com/efws/links.php?ex
Garrett