W3C home > Mailing lists > Public > whatwg@whatwg.org > July 2013

Re: [whatwg] Script preloading

From: Bruno Racineux <bruno@hexanet.net>
Date: Tue, 09 Jul 2013 18:31:41 -0700
To: Ian Hickson <ian@hixie.ch>, <whatwg@whatwg.org>, <getify@gmail.com>, <jaffathecake@gmail.com>, <travis.leithead@microsoft.com>
Message-ID: <CE0206DA.6AFD5%webmaster@hexanet.com>
I just joined the list and glad this subject is brought up.
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. I'll try to explain,
talk about the defer approach, as well as critical IE bugs that relate
to this very subject.

I think one of the reason that people may ask for this Interdependency
feature,
is due to the weakness of the platform they use, its plugins or the poor
management of such script (with often poorly conceived plugins not takign
dependency into account), which too often has the approach of loading all
scripts at all times regardless of the page context.

What's important to keep in mind, is that if you must have the browser
managing the interdependency, by association, you also have to manage it
at the app/platform level properly in the first place. Which seems awfully
redundant... And would probably lead to more page bloat or bad programming
habits.


As Kyle Simpson said, the primary motivation here is performance. Putting
scripts at the bottom, while preserving the scripts order has performance
drawbacks.
And 'async', while good for independent scripts such as social media apis,
is not really a good tools for dependency management.

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.

What we truly want is keep the order while loading script in a
non-blocking way.

Why not simply load all such scripts early in the <head> with 'defer',
which preserves the dependency order as determined by your app. Using
'defer' in head scripts is actually a very good way to preserve script
order with non-blocking scripts. And by loading the scripts very early in
the <head>, the possibility of a incurred significant delay of
DOMContentLoaded, for an eventual large script not yet downloaded, is
minimal to none.

In that sense, I think that too much focus has been placed on 'async',
with 'defer' having been extremely overlooked as such an adequate method
to non-blocking script loading with dependencies preserved. 'defer' after
all, is partly designed to guarantees that scripts execute in the order
they were specified and be delayed until document.readyState = interactive;

I sadly know there is a big hurdle for using 'defer' right now with
interdependencies, mainly with this IE9 bug
http://bugs.jquery.com/ticket/11310
Debunked in further details here (coincidentally, in part by Kyle Simpson):
https://github.com/h5bp/lazyweb-requests/issues/42


And may I get into further IE hate when it comes to the 'interactive'
state inconsistencies, by pointing to this very recent bug report I've had
to file:
https://connect.microsoft.com/IE/feedback/details/792880/document-readystat
e-interactive-firing-too-early-misfiring-in-ie11-9-and-10

Or should I beg the question, as to why it took my initiative yesterday
after almost a year of the problem being reported by others on github in
multiple occasions, to have this looked at so that IE11's final release
get it right, or not, who knows...

This problem exist since IE7! Is that really the best Microsoft can do?

There is something really wrong with the fixing process here. That, or too
big of a disconnect between those who test and those who are supposed to
fix things.
Or it is that developers are too fed up with those bugs, having to find
ways around them, to find the energy to report them appropriately?

Thankfully, the IE7-9 'defer' bug is has been fixed in IE10. Yet it's
likely postponing proper use of 'defer' for another what? 5 years?. Thanks
to Microsoft once again for holding the internet back and make our life
harder? Is that all we can come up with?

I would actually advocate to petition Microsoft to release patches for
IE8, IE9 and IE10 for these particular stupid overlooked bugs, which some
days honestly make me want to kill myself.

I understand that in some areas, older browsers cannot add or remove
features to the same major release for good reasons. But it's a real
problem if bugs of this kind ( which wouldn't break any site if fixed
now), cannot be fixed on older browsers using regular Windows updates. The
idea that a browser is set in stone on release, and cannot be touched
become a real issue to progress. Aren't those two particular bugs good
example of thing that should be fixed and applied along security patches?
And not have to wait 5 to 10 years coping with buggy browsers for no good
reasons I can think of.


I would also strongly favor restoring the previous spec portion of 'defer'
which allow to have defer on inline script blocks (i.e. if the src
attribute is not present). I don't know why this html4 functionality was
removed from html5?
I see use cases which would give much more flexibility with dependencies
(such as putting jquery on 'defer' in the head with inline 'defer' jquery
functions) and possibly even improving performance significantly.

And I am not saying that 'defer' is the only answer to script loading, but
at least if it worked across browser we would be here in this poor pitiful
state of not being able to use features that date back to HTML4 and should
be working on all browsers properly by now, to do such simple things as
deferring jQuery scripts.

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.




On 7/9/13 12:39 PM, "Ian Hickson" <ian@hixie.ch> wrote:

>
>A topic that regularly comes up is script loading.
>
>I sent an e-mail responding to related feedback last year, though it
>didn't get any replies to the script loading parts of it:
>
>   
>http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Dec/0221.htm
>l
>
>It seems that people want something that:
>
> - Lets them download scripts but not execute them until needed.
> - Lets them have multiple interdependent scripts and have the browser
>   manage their ordering.
> - Do all this without having to modify existing scripts.
>
>I must admit to not really understanding these requirements (script
>execution can be made more or less free if they are designed to just
>expose some functions, for example, and it's trivial to set up a script
>dependency mechanism for scripts to run each other in order, and there's
>no reason browsers can't parse scripts off the main thread, etc). But
>since everyone else seems to think these are issues, let's ignore that.
>
>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.
>
>Would something like this, based on proposals from a variety of people in
>the past, work for your needs?
>
>1. Add a "dependencies" attribute to <script> that can point to other
>   scripts to indicate that execution of this script should be delayed
>   until all other scripts that are (a) earlier in the tree order and (b)
>   identified by this attribute have executed.
>
>     <script id="jquery" src="jquery.js" async></script>
>     <script id="shims" src="shims.js" async></script>
>     <script dependencies="shims jquery" src="myscript.js" async></script>
>
>   This would download jquery.js, shims.js, and myscript.js ASAP, without
>   blocking anything else, and would then run jquery.js and shims.js
>ASAP, 
>   in any order, and then once both have executed, it would execute
>   myscript.js.
>
>2. Add an "whenneeded" boolean content attribute, a "markNeeded()" method,
>   and an internal "is-needed flag" (initially false) to the <script>
>   element. When a script is about to execute, if its whenneeded=""
>   attribute is set, but its "is-needed" flag is not, then delay
>   execution. Calling markNeeded() on a script that has a whenneeded
>   boolean but that has not executed yet first causes the markNeeded()
>   method on all the script's dependencies to be called, and then causes
>   this script to become ready to execute.
>
>     <script id="jquery" src="jquery.js" async whenneeded></script>
>     <script id="shims" src="shims.js" async whenneeded></script>
>     <script id="myscript" dependencies="shims jquery" src="myscript.js"
>             async whenneeded></script>
>
>   This would download jquery.js, shims.js, and myscript.js ASAP, and
>then 
>   wait for further instructions.
>
>     document.getElementById('myscript').markNeeded();
>
>   This would then cause the scripts to execute, first jquery.js and
>   shims.js (in any order), and then myscript.js. If any hadn't finished
>   downloading yet, it would first wait for that to finish.
>
>   (We could make markNeeded() return a promise, too.)
>
>Is there a need for delaying the download of a script as well? (If so, we
>could change whenneeded="" to have values, like whenneeded="execute" vs
>whenneeded="download" or something.)
>
>Is there something this doesn't handle which it would need to handle?
>
>-- 
>Ian Hickson               U+1047E                )\._.,--....,'``.    fL
>http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
>Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
Received on Wednesday, 10 July 2013 01:32:10 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 17:00:03 UTC