Re: Executing script-inserted external scripts in insertion order

On Mon, Oct 11, 2010 at 7:22 AM, Getify <getify@gmail.com> wrote:
>>>> The problem I have with simply speccing that script-inserted external
>
> script that don't have the async attribute maintain order among themselves
> is that it gives no way for LABjs to prepare for WebKit and IE implementing
> the spec at a later date.
>
> I agree that avoiding UA sniffing or inferences and getting to a point where
> we can feature-detect on this behavior is the best ultimate goal. However, I
> think the stretch of optimism to suggest that quickly Opera, Webkit/Chrome,
> *and* IE will all fall in line is a bit much -- in fact, I think it may be
> quite awhile before we get convergent behavior. Moreover, the older browsers
> will be around for a long time with the divergent behavior. As such, I think
> browser inferences will be the only practical solution for LABjs (and
> related projects) to pragmatically serve all those browsers.
>
> I don't think that introducing a new property/attribute ("ordered") into the
> mix will ensure any sooner convergence of behavior. While looking for
> "ordered" may provide a shorter-term feature-test, the same inference and
> forking behavior will have to be maintained for quite awhile until we have
> full convergence (and older divergent browsers are practically
> insignificant), and thus the feature-test helpfulness will be diminished.
>
> We could just as easily say that feature-test for `async` (and specifically
> its default value, either true or false) is the feature-test for ordered vs.
> non-ordered behavior. This feature-test will fail for awhile, but once we
> eventually have the convergence (and thus inference forking is moot), that
> feature-test will be just as reliable as a feature-test on "ordered". But
> it'll have the added benefit of better symmetry and simplicity. By symmetry,
> I mean that `async` is fully spec'd out to affect script tags in the HTML,
> but it's not spec'd to do anything (AFAIK) to injected scripts behavior --
>  so extending its meaning to injected scripts brings them into more
> consistency with each other.

Note that 'async' is supported in Firefox 3.6, so this might not work.

>>>> * The time after the future. We should minimize the cruft accumulated as
>>>> a side effect of getting from the present to the future so that it doesn't
>>>> haunt us after we've gotten to the future.
>
> Agreed. I'd say `ordered` might qualify as future cruft if `async` will do.
>
>>>> <jgraham> Doesn't it make more sense to make preserving order the
>>>> default
>
> It makes more sense to a web performance optimization person like me. It's
> the more ideal of the behaviors as compared to the non-preserving order by
> default in IE/Webkit/Chrome. In fact, I always wanted and assumed that the
> most proper (performance-savvy) behavior would be to have order-preservation
> by default, and then turn disable order preservation with `async`.  This
> constitutes a very ideal scenario for script-loaders.

I disagree that ordering is better from a performance point of view.
Consider a browser that today execute DOM inserted scripts as soon as
they are downloaded, i.e. it does not enforce order-preservation. For
such a browser it would strictly be a performance degradation to start
enforcing evaluation order.

I do however agree that preserving order has other benefits. In
particular it makes evaluation much more consistent and much less
prone to racy behavior that depends on network speed of one vs.
another script. This was the main reason I originally implemented
enforced evaluation order in Firefox many years ago.

However since then I've gotten a lot of push-back and encouragement to
use the webkit/IE way of more aggressively evaluating scripts as soon
as they are downloaded. Better performance was always the cited
reason.

> However, I do not know if there are really other compelling use cases for
> the opposite to be default.  For instance, if jQuery is injecting scripts
> and is bothered by some side-effect of them having order preservation, is
> there REALLY a reason that jQuery couldn't just add the `async` property
> (true) to the injected scripts, and thus opt-in to the behavior desired?

I don't think side effects is the main concern, but rather
performance. Consider the case when you have several parts of a page
with some form of UI attached to them. If the different parts are
driven by independent <script>s, you'd get a better experience if each
given part starts working as soon as the <script> for that part is
downloaded.

I personally agree that preserving order is a better default. People
can always set .async if they know that a given script doesn't have
still-unloaded dependencies. However I think it's more important that
all browsers behave the same, and I thus far have thought it would be
unlikely to be able to convince webkit/IE to start enforcing order
given that this would be a performance hit for them.

> Since injected scripts must always be controlled by some script logic that
> is doing the injecting, it would seem either side of the fence could change
> to start setting the property's value to the opposite of its default, and
> thus achieve what they need.
>
> So in that respect, I'm not sure there's a compelling argument for either
> way to be the default. FWIW, I won't live or die by whichever one turns out
> to be the default behavior, as long as the other behavior is still available
> to me by changing the `async` (or some other, I suppose) attribute.

Agreed. Whichever default we pick I think we need to make the other
option available through some means. What means that should be
probably depends on what we pick as the default.

So asking the webkit/IE developers: Would you consider changing
default behavior to be to enforce order?


> Actually, there is another interesting use case somewhat unrelated to
> performance-oriented script loaders for why the "text/cache"
> fetching/caching behavior is helpful. Some templating techniques, including
> jQuery's templates as recently being released and made more popular, use a
> script node in the HTML with a fake type to store content such as HTML
> templates, which can later be fetched (by `id`) and used by JavaScript for
> presentation purposes.
>
> If the standard were to be extended that fake mime-types (or even, exactly
> "text/cache") should download the contents into the script element (and the
> cache) but not try to automatically parse them, then users of such
> templating tools could load templates from external resources instead of
> inlining them into the markup. This of course has benefits for caching
> (performance), etc.
>
> To be clear, for that use case to be served, not only would the resource
> need to be fetched by the "text/cache" node, but also made available to
> script via the `text` property of the node.

This is certainly an interesting use-case, but I'd prefer to solve
that separately from this discussion, for several reasons. First of
all if we are to expose the contents of the fetched resource, we have
to limit it to same-site or use CORS, which would be a significant
departure from how <script> works. Second, <script> is already
complicated as it is, so trying to overload it to wholly
non-script-related functionality will likely add unnecessary
complications.

>>>> It may well be worthwhile to consider a pessimistic approach that starts
>>>> with the assumption that Gecko and Opera won't be able to get rid of ordered
>>>> execution of script-inserted external scripts that don't have the async
>>>> attribute and that IE and WebKit won't be able to get rid of supporting
>>>> preloading text/cache scripts.
>
> I'd say from my perspective the pessimistic approach is as I mentioned
> earlier, which is that we'll have practical real-world divergence for quite
> awhile, even well beyond when the spec is amended to address this problem.
> We should then opt for the smallest change to spec that will eventually
> address the needs, and then hope and advocate for newest generation browsers
> to implement that change as soon as possible. Either way, script loaders
> like LABjs aren't going to be able to retire inference-forking code any time
> soon. :/

I agree. I think it's too much to expect that browser-sniffing can
immediately be replaced. We should do our best to try develop the
tools to make it unnecessary, but it will take time before those tools
are deployed and debugged, as well as for old browsers to lose market
share.

However I also think that it's great if developers raise issues with
browser vendors when they do feel the need to use browser sniffing. I
wish that this issue had been raised with any browser vendor or either
HTMLWG or WhatWG a long time ago. All too often problems can easily be
solved in browsers and specs, but the issue is never highlighted and
instead workarounds are deployed. So I really appreciate that you
joined the list to help us find a solution to this problem!

/ Jonas

Received on Tuesday, 12 October 2010 02:43:33 UTC