W3C home > Mailing lists > Public > public-html@w3.org > October 2010

Re: Executing script-inserted external scripts in insertion order

From: Getify <getify@gmail.com>
Date: Sun, 17 Oct 2010 23:31:48 -0500
Message-ID: <61BFD52CE7D6453FA28AB2C86B5525D0@spartacus>
To: "Adam Barth" <w3c@adambarth.com>, "public html" <public-html@w3.org>
?> Can you provide examples of sites that break?  It's easier to reason
> about concrete broken sites than about these things in the abstract.

I've provided several examples earlier in this thread of sites that will 
break either with the Mozilla change (ordering) or the Webkit change (not 
fetching invalid mime-type scripts). Briefly:


For these sites, the Webkit breakage will be because LABjs is relying on (in 
IE/Webkit) the ability to fetch a script into cache but not have it execute, 
using what I call the "preloading" trick. It works by injecting a script 
node with `type=script/cache` that will load the script into cache but not 
execute it. Moreover, the load still fires the `onload` event, so LABjs 
knows when the script is successfully in the cache, and can then, in the 
proper execution sequence, immediately execute the script by re-injecting 
the same source URL but with the correct `type=text/javascript`.

I understand that this seems exactly like <link rel=prefetch>, which is true 
on the surface that LABjs could possibly be changed to use that trick 
instead of the invalid mime-type trick. However, this option is bad because:

1) as I said, there doesn't seem to be a valid feature-test to know in which 
version Webkit stops supporting the fetch-but-not-execute behavior, so 
backwards-compat and existings sites/content will be vulnerable.

2) the "preloading" trick, whether it uses `script/cache` or `prefetch`, is 
far sub-optimal for the loading use case in question. It's only been a hack 
fallback for IE/Webkit thus far because up until now there hasn't been 
another option. But it's very susceptible to breaking if even one of the 
scripts being loaded via "preloading" fails to send out proper cache 
headers. Some studies/experts in this area have suggested that as much as 
70% of scripts on the web are not sent out with proper headers, so even if 
that estimate is twice as much as reality, 35% of scripts will completely 
break with this trick.

Thus, I do not feel that "preloading", regardless of technique used, is a 
valid spec'd long-term solution to the use-case.

What we need specifically is a way to load a list of scripts (each only 
once) in parallel but be able to specify that their execution order matters 
(dependencies), so the order should be enforced as insertion order.

This behavior is already something that HTML script tags provide, we're just 
asking that it also be available opt-in to script-inserted script nodes as 
well, via setting `async` to false specifically.

> Isn't this what defer does?  I guess you're saying it's not
> performance-oriented?

`defer` tells the browser to wait until the DOM is finished before executing 
the scripts. Yes, it does eventually execute them in order, but pinning 
scripts' execution to the DOM is where it fails to meet the performance 
optimization mark as desired. It's also unclear if `defer` scripts delay 
*download* until after the DOM (some tests in some browsers suggest so) or 
just execution, which would be even less "performance-oriented". Moreover, 
it's also unclear if `defer` scripts being injected long after DOM would 
still maintain order, etc.

These questions, and others like it, are why I feel that `async=false` on a 
dynamically-inserted script is a better switch than `defer` for the behavior 
we're looking for.

> I believe tonyg said that he thought the proposed change would slow
> down a bunch of real-world web sites that use script-inserted scripts
> to achieve parallel loading in existing browsers.  Generally, folks
> aren't going to be that exciting about slowing down web sites.

Here's why I assert that the change in question will NOT slow down existing 
sites for IE/Webkit: because I'm arguing that I think it makes sense 
compat-wise for browsers (and spec) to implement `true` as the default value 
for `async`, but *only* on script-inserted scripts. Of course, that makes 
the default opposite of what how it defaults to `false` on parser-inserted 
scripts, which might seem odd at first glance but I think is logically 
defendable upon examination.

Not only would that default mean protecting all existing content in 
Webkit/IE that relies on unordered (faster) execution of script-inserted 
nodes (since the default for those scripts would still be `true` and thus 
unordered), but it would also provide an effective feature-test for script 
loaders by being able to look for not only the `async` property on a script 
node but also its default value being `true` (as opposed to the `false` 
default it has now).

var el = document.createElement("script");
var ft = ("async" in el && el.async == true);

Received on Monday, 18 October 2010 04:32:25 UTC

This archive was generated by hypermail 2.3.1 : Thursday, 29 October 2015 10:16:06 UTC