[whatwg] Script preloading
getify at gmail.com
Mon Jul 22 16:01:13 PDT 2013
> Do you have a link to your preload proposal?
My main `<script preload>` proposal (skip the first section of this LONG email, proposal starts at "Summary:" several paragraphs down):
Then proposal slightly amended here:
> 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".
FWIW, I believe script loaders, at least as I envision them, would use BOTH the `onpreload` AND the `onload` events, since marking a script as ready-to-execute, however that's done, is unlikely to be a synchronouse event, so the script loader would still want to listen for when it finished running (hopefully pretty soon after being told it's OK to run!? :)
I see the `onpreload` as similar in spirit to the non-standard and now-phased-out-as-of-IE11 `script.onreadystate` mechanism, which provided more detail about the status of a script as progressed from request to completion. `onpreload` just, to me, fills the spot of what semantically the word "load" meant, but since everyone knows "load" in the context of scripts means "load and process/run", we can't lightly just change "load".
If `onpreload` seemed to imply something too far outside the normal state progression of a script, it could be called `onfinishload` or `onfinishrequest` or something like that. In the `onreadystatechange` world, they called that state "loaded", FWIW.
> Generally speaking "load" means "loaded and processed". The
> 'noexecute' flag would change what the "and processed" piece includes.
I still think, though, that it's problematic to overload "load", because as mentioned above, as a script loader, I'd want to know about both events ("finished load" and "finished execution"), not just a binary switch between one or the other. If load fired twice, that seems (potentially) awfully confusing. If load fired early (at load finish), and there was no more event for "finished execution", script loaders would be quite hampered (at least as I envision architecting one) because they couldn't know if a script had really run yet or not, only that they asked it to be eligible to run.
> 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).
Agreed. `window.onerror` serves fine case #3. What we don't seem to have as consistent cross-browser behavior, or even terribly well defined in the spec, is #1 and #2, especially #1. Various older browsers had different interpretations as to which network conditions constituted "load complete" or not.
Obviously, the 200 (and several other 2xx's) should be success. And I'd think it would be obvious that any of the 4xx and 5xx codes were error.
But perhaps it should just be: did the network request result in a non-empty payload?
Now, for #2, to my non-implementor eye, that seems pretty well definable too. But again, cross-browser mayhem was bad with this. IIRC, Opera fired the onerror in the case of bad compilation, but none of the others did. Or maybe it was vice versa. Been awhile since I looked specifically. Just for sure recall inconsistency here.
> 1 and 2 seems like they could behave exactly the same for noexecute
> scripts as for normal scripts.
Yes, as long as all the spec makes it clear what the do's and don'ts here are, and everyone complies. :)
> I'm not sure if that includes firing
> both A and B in current browsers?
They do not seem to fire `window.onerror` in either #1 or #2 IIRC, but they do in #3.
If I could have it my way, I'd have all three errors firing on the script.onerror, and not involve window.onerror. The reason is because `window.onerror` is notoriously hijacked by various RUM libraries and such, to do remote logging of errors, so a script loader attaching to window.onerror and catch is not terribly reliable in my experience.
But I'm fine with whatever combination gives reliable and non-overlapping and non-gaping error handling coverage. :)
> 3 presumably only triggers B currently for normal scripts?
> Indeed. Though we're only talking about the A mechanism about, right?
Correct. Although in an ideal world (for me), B would be more reliable, as noted above.
> 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>
Sure. Though as noted, script loaders may have limited utility of window.onerror when they run in unfamiliar/hostile pages which already hijack that error.
> Can we get a good "markup-only" solution while still keeping both
> acceptable performance as well as correct functionality in downlevel
In older browsers both <script dependencies> and <script preload> would fall back to normal script loading semantics, as you noted. I think that's fine, because those older browsers have no reliable markup-only mechanism for this anyway.
Speaking of "no reliable markup-only mechanism", <script async dependencies> sounds like it's trying to be a more powerful replacement of `<script defer>`, which was fine in theory but is so horribly plagued with old browser bugs that it can't reliably be used in most situations right now (ie, can't be used with more than one <script> at a time). Moreover, <script defer> had no real meaning in the dynamic-after-page-load-loading scenarios, whereas <script preload> and <script dependencies> would both be useful in markup-only or dynamic-loading scenarios.
More information about the whatwg