[whatwg] Script preloading

Jonas Sicking jonas at sicking.cc
Mon Jul 22 15:22:32 PDT 2013

On Mon, Jul 22, 2013 at 2:35 PM, Kyle Simpson <getify at gmail.com> wrote:
> FWIW, I'd be much more in favor of Jonas' proposal, at this point, than the dependencies=.. proposal. The `noexecute/execute()` is conceptually pretty similar to the preload proposal I've been pushing. As far as I can tell from how Jonas describes it, it looks like it would fit most of the use-cases I've put forth as caring about.
> There's a few details to iron out, however:
> 1. Will it cause confusion for authors that the behavior of the `onload` event on script elements is modified from its current long-standing "loaded and executed" to just "loaded" when in the presence of the `noexecute` attribute/property? Seems like it could cause a fair bit of confusion.
> That's why the preload proposal proposed another event (`onpreload`), to reduce the conflation/confusion. But it might be tenable for authors. I'm sure as a script loader author I can work around it just fine if I need to.

Do you have a link to your preload proposal?

Either way, I agree about the concern with onload. I personally have a
hard time telling if it'll be confusing.

Having the load event anytime we are done with a network request also
seems beneficial. Rather than having most APIs use "load" whereas this
would use "preload".

Generally speaking "load" means "loaded and processed". The
'noexecute' flag would change what the "and processed" piece includes.

But I'm fine either way here. The same question and risk of confusion
seems to exist with the "whenneeded" attribute. In general
"whenneeded" seems very similar to "noexecute", but with a little bit
more stuff done automatically, for better or worse.

> 2. What will the interaction be, if any different, with the `onerror` events? Script preloading not-withstanding, there's little cross-browser compatibility on the topic of just what exactly constitutes a script "error" event. Some browsers fire it for all of the common network error conditions (404, 5xx), others only some of them.

There are three opportunities to fire "error stuff" here:

1. Failed network request
2. Failed JS compilation
3. Exception thrown from execution

And there are two error reporting mechanisms in play

A. Fire an "error" event on the <script> element.
B. Fire the window.onerror callback (like an event, but not exactly the same).

1 and 2 seems like they could behave exactly the same for noexecute
scripts as for normal scripts. I'm not sure if that includes firing
both A and B in current browsers? This would require implementations
to do syntax checking (though not full compilation) of the script even
before the execute() function is called. I *think* this is ok, but I'm
not sure. Measurements in browsers would likely be needed.

3 presumably only triggers B currently for normal scripts?

> In particular, if we're just building off existing mechanisms and not inventing whole new ones, it would be nice, from an author perspective, if EITHER the `onload` or the `onerror` event ALWAYS fired, and never both, and never neither, and if it was consistent when each happened.
> I asked a couple of years ago on this list for that exact thing to be clarified in the spec, and was told at that time that implementors were left with the discretion, which accounted for the disparity. I of course would renew my request to reverse that and land on some common spec.

Indeed. Though we're only talking about the A mechanism about, right?

I.e. the following would cause both a "load" event to be fired on the
<script>, and window.onerror to be triggered?

<script src="data:text/plain,throw new Error();"></script>

I would definitely be in support of that. Though compatibility with
existing content could be a problem.

> 3. The main reason people seem to favor the `dependencies=..` proposal or its variants is the idea of "markup-only" preloading, where the loading of a subsequent script tag or tags can implicitly be the signal to execute another previously loaded-and-waiting script. Not clear if/how Jonas' proposal could suit that view. Perhaps similar to how I proposed handling that desire in the preload proposal.

Can we get a good "markup-only" solution while still keeping both
acceptable performance as well as correct functionality in downlevel

I.e. something like:

<script src="script1.js" id="s1">
<script src="script2.js" dependencies="s1">

would run correctly in downlevel browsers, but would force the scripts
to be blocking.

<script src="script1.js" id="s1" async>
<script src="script2.js" async dependencies="s1">

would give you performant non-blocking behavior in downlevel browsers,
but at the expense of the scripts not always running in scripts in the
right order.

/ Jonas

> --Kyle
> On Jul 22, 2013, at 4:00 PM, Jonas Sicking <jonas at sicking.cc> wrote:
>> On Tue, Jul 9, 2013 at 12:39 PM, Ian Hickson <ian at hixie.ch> wrote:
>>> The proposals I've seen so far for extending the spec's script preloading
>>> mechanisms fall into two categories:
>>> - provide some more control over the mechanisms already there, e.g.
>>>   firing events at various times, adding attributes to make the script
>>>   loading algorithm work differently, or adding methods to trigger
>>>   particular parts of the algorithm under author control.
>>> - provide a layer above the current algorithm that provides strong
>>>   semantics, but that doesn't have much impact on the loading algorithm
>>>   itself.
>>> I'm very hesitant to do the first of these, because the algorithm is _so_
>>> complicated that adding anything else to it is just going to result in
>>> bugs in browsers. There comes a point where an algorithm just becomes so
>>> hard to accurately test that it's a lost cause.
>>> The second seems more feasible, though.
>> FWIW, I don't really know what functionality you put in the first
>> category, and what you put in the second.
>> However, as an implementor, I definitely think that the current
>> proposal is more complicated to implement than the proposal that I
>> pushed for before. I.e. adding a "noexecute" attribute on the <script>
>> element which causes the script element not to execute when it
>> normally would. Instead it fires the "load" event when the script has
>> been loaded and does nothing more.
>> Once the page wants the script to execute, it would call a new
>> .execute() function on the script which would cause the loaded script
>> to execute. If the function is called before the load event has fired,
>> an InvalidStateError exception would be thrown.
>> I could absolutely believe that this is harder to specify than your
>> proposal. I haven't looked at the spec in enough detail to know. But
>> it's definitely easier to implement in at least Gecko. I'd be
>> interested to hear what other implementors think. And implementations
>> have a higher priority than spec writing in the hierarchy of
>> constituents.
>> I also think it's a simpler model for authors to understand.
>> Now, even higher priority in the hierarchy of constituents are
>> authors. So if your proposal above is written with the goal of
>> creating something authors prefer over the noexecute proposal, then
>> that definitely seems like the right goal. I haven't read enough of
>> the feedback here to get a clear picture of if the proposal in this
>> thread is considered better than noexecute.
>> I could definitely see that the "dependencies" feature could be
>> attractive if it indeed would let authors avoid manually scheduling
>> scripts for execution. But as always when building high-level
>> features, there's a risk that if they don't solve the use-cases
>> exactly, that they won't get used.
>> / Jonas

More information about the whatwg mailing list