[whatwg] Script preloading

Bruno Racineux bruno at hexanet.net
Wed Jul 10 03:31:31 PDT 2013


On 7/9/13 7:09 PM, "Kyle Simpson" <getify at gmail.com> wrote:

>> I have been wrestling pretty hard with script loading issues lately. I'd
>> say that having the browser manage script interdependency is probably a
>> bad and cumbersome way to solve these issues.
>
>What do you mean by "having the browser manage script interdependency"?
>As far as I am aware, this thread and these feature requests are not
>about the browser managing script interdependenciesŠ in fact, quite the
>opposite. What we're asking and hoping for is a facility that allows the
>app code to manage the dependencies and the loading order, while only
>relying on the browser to do the actual loading for us the way it always
>has.

Maybe we diverge on semantics. When you say "while only relying on the
browser to do the actual loading for us the way it always has". That's not
really what I am seeing.

The suggestion #2. given by Ian is not only doing the loading per say.
The browser has to figure out the dependencies from the dependency
information given in a DOM format. That's essentially what I mean by
delegating the dependency management to the browser.

Anyway, as per your previous email I think we mostly agree that solution
#1 is not very practical (or infeasible per your word) and #2 is awfully
complex.

>The only part of that puzzle that's missing is a way to tell the browser
>to pause between finishing-loading and starting-executing. Asking for
>such a mechanism has really nothing to do with offloading dependency
>management to the browser to handle. It's empowering the app code to be
>more in control, not less.
 
I think that preloading without executing is really what we should are
after.
But there has to be a simpler way to do this.

>
>
>> I think one of the reason that people may ask for this Interdependency
>> feature,
>> is due to the weakness of the platform they use,
>
>Again, I think you may possibly be misunderstanding the goal of what's
>being asked for. But I'll agree with you that there's a weakness. The
>weakness, IMO, is in the web platform itself, in not giving us more
>fine-grained control over script loading. That is why we keep having this
>discussion every 6 months or so for the least several years. The
>use-cases never go away, and the hacks we use to deal with them never get
>any less ugly.
>
>> And 'async', while good for independent scripts such as social media
>>apis,
>> is not really a good tools for dependency management.
>
>Again, possibly a case of misunderstanding or missed context from
>previous conversations. When I bring up "async", I'm not talking about
><script async> in markup as you suggest, but actually `script.async =
>false` being set on dynamcially created script elements (in code).
>"async=false" (aka "ordered async") is a relatively "new" feature added
>to the platform about 2.5 years ago that gives us async parallel loading,
>but the browser automatically enforces execution order to be request
>order, instead of ASAP order.
>
>"async=false" is actually a good feature. The problem is not the feature
>itself, but that it's only part of what we needed.

I see. I am shamefully new to the notion that async=false is "ordered
async". It apparently went quite off specs through vendors first to make
this work, with no much of an official documentation, hence me missing it
I guess... Though it kind of make me cringe that vendors jumped on
implementing such new slightly unintuitive feature, while HTML4 specs like
'defer' were left unreliable. It feel like priorities worked slightly
backwards...

Nevertheless "ordered async" is very useful as solving part of the problem
indeed.


>
>> My main issue against using external script loaders like LABjs and
>>others,
>> has always been that if the browser must download a script first, before
>> starting to download the dependencies. It presents a drawback already,
>>for
>> delayed the scripts by the script loader's latency and download time (at
>> least for the first uncached page load) similarly to having scripts at
>>the
>> bottoms.
>
>For LABjs' part, I never suggest to people to load LABjs in a separate
>file. I suggest that people use a "bootstrap" type code file, which would
>be a single .js file they load with a single <script> tag in their
>markup, and it contains all the bare-minimum code necessary to bootstrap
>the page/app. It would include the code for LABjs, also the $LAB chains
>for loading other scripts, even basic event handling or other bootstrap
>type logic.
>
>Moreover, the extra ~2k of gzip-bytes that LABjs "costs" (even if it's a
>separate file, but especially if it's included in another bootstrap file)
>is almost always made up for in savings by being able to take advantage
>of consistent parallel loading of scripts.
>
>If your page only has 3-5k of JS on it, then you shouldn't use a script
>loader. But if you're like most sites, and you're loading 100-300k of JS,
>then a tiny 2k of JS for loading optimization is not even a drop in the
>ocean.

It's not the size that bothers me. It's the inevitable first time delay.
Ideally all scripts needed before window.load should all fire at the same
time, right away in the head, for maximum performance. Having to wait for
any script first, is delaying another 300ms+. I am not saying, I am
against script loaders just for that, but it's not optimal for first time
page views. The idea of preloading script without executing them and find
a way to call them only when needed goes towards the same performance
goals.

The preferred approach I have taken, is having a minimal inline script
that takes care of loading a compact list of async scripts, good
especially for external script likes social media buttons or google
analytics. Each of these async snippet generally being a redundant piece
of code of a similar createElement('script'). Some of them being placed in
the <body>, which unnecessary delay some more, especially if those script
call an api for more script after that, which keep delaying the
window.load further.

I first load the scripts from the <head> and proceed to their inits
separately on DOMReady with bottom inline script. If the scripts are no
yet loaded, I go though ajax which either picks up on the current stream,
until finished loading, or should the script have failed loading, would
fall back to a new ajax load, postponing the callback for initialization
until complete. If you want to have a look for mere curiosity you can see
the source of: http://www.digitalcinemasociety.org/digital-cinema-society


>Lastly, I advocate the techniques of deferring certain parts of your
>scripts to not loading during page-load at all, but instead post-loading
>or on-demand loading at later times. This amounts to needing to have the
>ability to do dynamic loading during the lifetime of the page. Markup
>alone is never enough for that. You have to have a script loader of some
>sort.
>
>So, I advocate that a tiny but powerful script loader that you use for
>BOTH uses is a win. You use the same script loading techniques for
>page-load loading as you do for on-demand loading. Consistency of toolset
>here makes coding and maintenance easier in the long run.
>
>> Why not simply load all such scripts early in the <head> with 'defer',
>
>As you mention below, defer is horribly buggy and unreliable. The chances
>of IE8+ (not to mention IE6-8) being patched to have better defer are
>roundable to zero.
>
>
>
>> 'defer' in head scripts is actually a very good way to preserve script
>> order with non-blocking scripts.
>
>But it only works for external scripts (as you note below), and it only
>works for markup loading during page-load, and gives no answer for
>dynamic/on-demand loading later. As such, by design, it's insufficient
>for the use-cases presented.
Nods. I found ways to deal with a reliable 'interactive' state
cross-browser but ordered 'defer' seems like a lost cause.

>
>
>> I would actually advocate to petition Microsoft to release patches for
>> IE8, IE9 and IE10 for these particular stupid overlooked bugs
>
>While this sounds nice in theory, it would actually be MUCH worse if they
>ever did that. Most of the people locked on those older browsers are
>locked down and not getting any updates. But not all of them. Some people
>WOULD get the update. So then we'd be left with a lot of inconsistency
>where everyone says "we support IE8", but then there's this big
>difference with IE8 between IE8.0 and IE8.0.1 or whatever.
>
>That kind of nuance would significantly complicate and make this stuff
>MUCH harder to deal with predictably. They almost certainly would NOT be
>able to patch those browsers in a feature-testable way (and what does
>feature-testable even mean when we're talking purely about markup!?!?),
>so then we'd have to do crazy crap like UA version parsing on the server,
>etc.

Such issue of predictability doesn't come up for Safari or Chrome's minor
versions.
I don't see why IE would have different standards. To be clear I am only
talking about things that no one actually use because it doesn't work in
the first place or things that pertain to feature detection in javascript.
Perhaps if we have been so wrongly focused with browser sniffing for IE's
versions, rather than feature detection, is due to such a lack of regular
bug fixing update policies with IE...

Introducing a stupid compatibility mode vs standard mode, is far worse
non-sense to me, or for a regular user to understand, than breaking a few
sites for making things work as initially intended, by fixing a few bugs.
The idea of "I want my new browser to render like an old one" is deranged
IMO. But I digress.

>
>> Back to the initial question from my rant. While there is a use case for
>> not downloading or executing scripts until needed, this can somewhat
>> already be dealt with using ajax or the post-eval method google uses. Or
>> perhaps this script execution hold could be an ajax only solution, with
>>a
>> no-execute-yet property and a pure javascript behavior, rather than also
>> implicate DOM attributes into this.
>
>Unfortunately, the death of XHR based loading is still that scripts are
>often loaded cross-domain. The older browsers IE>=7 didn't support CORS
>at all, so total deal breaker. IE8 and IE9 supported a bastardized
>version of CORS, but few devs ever supported XDomainRequest instead of
>the standardized CORS on XHR. Also, eval'd or script-injected code loaded
>via XHR is significantly less debuggable than normal <script> loaded code.
>
Fair point!





More information about the whatwg mailing list