This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 21074 - Need ability to load scripts without blocking onload
Summary: Need ability to load scripts without blocking onload
Status: RESOLVED WONTFIX
Alias: None
Product: HTML WG
Classification: Unclassified
Component: HTML5 spec (show other bugs)
Version: unspecified
Hardware: All All
: P2 enhancement
Target Milestone: ---
Assignee: Robin Berjon
QA Contact: HTML WG Bugzilla archive list
URL: http://www.lognormal.com/blog/2012/12...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-21 16:15 UTC by Philip Tellis
Modified: 2016-04-20 19:19 UTC (History)
10 users (show)

See Also:


Attachments

Description Philip Tellis 2013-02-21 16:15:29 UTC
The URL describes this in detail, but I'll describe a summary here.

Current Situation:

We include scripts in an HTML document using the <script> tag:

<script src="script-url" type="text/javascript"></script>

In this case, parsing and rendering of the document blocks until the script has been downloaded, parsed and executed since the script might change the document using document.write.

If the script does not use document.write, the developer can use the async attribute to tell the browser that it can continue loading, parsing and rendering the page in parallel with the downloading, parsing and execution of the script:

<script async src="script-url" type="text/javascript"></script>

However, this script will still block the onload event (not clear in the spec, but all implementations appear to do this).


Required Enhancement:

We should either add a new attribute: "nonblocking", or add a new attribute value for the async attribute: async="nonblocking".  It would work as follows:

<script async="nonblocking" src="script-url" type="text/javascript"></script>

This provides a hint to the user agent that it should start downloading, parsing and executing as soon as possible but it should not block the onload event (or any other event) of the containing document waiting for this script to download, parse and execute.

This should also be usable in dynamically injected script nodes.

User Agents that treat async as a boolean attribute will fall back to the current model.

Why do we need this?

Third party scripts are included in websites all over the Web.  If one of these third party servers becomes unresponsive (eg: DNS failure, host timeout, etc.), this will block the onload event on all sites that include the third party script even if the async attribute is used.

Since many sites perform some amount of page setup tasks in the onload event handler, this could block these tasks indefinitely depending on timeout values.

The only option now available is the iframe hack described in the attached URL.
Comment 1 Philip Tellis 2013-02-21 16:16:33 UTC
It would also be nice to have this for iframes so we do not block onload waiting for ads to load.
Comment 2 Travis Leithead [MSFT] 2013-02-21 16:25:33 UTC
Another alternative to simply telling the script not to block the load event, is to instead allow the developer to specify the timeout value for a script (since you would have to opt-in to a new attribute 'noblocking' anyway--I expect that problematic script libraries would need to be known a-priori so this would work...).

For example:
<script src="script-url" async timout="2s"></script>

Would still block the load event for up to 2 seconds in the worst-case and would then abort the connection and fire the load event.

Thoughts?
Comment 3 Philip Tellis 2013-02-21 16:33:56 UTC
The timeout has a use case, but I don't think it is a replacement for nonblocking.

for example, you may not want to abort the download.  you might still want to let it load up whenever it does.

Consider a server that generally responds in 50ms, but in 1% of cases takes more than 5 seconds to respond.  The user will most likely still be on your page 5 seconds after it starts loading, so the script load will complete, and can still do what it needs to (eg: stats gathering, or a widget at the bottom of the page).

Blocking onload for 2 seconds is also not acceptable because we may be blocking execution of scripts for something that really does not care about the onload event.
Comment 4 Travis Leithead [MSFT] 2013-02-21 16:38:06 UTC
I wonder then if we can't just integrate the semantics of non-blocking into the existing async attribute?

Are there specific use cases where you want async-but-blocking?
Comment 5 Philip Tellis 2013-02-21 16:57:23 UTC
Possibly in the case where an onload handler depends on functionality provided by the script.
Comment 6 Lee Kowalkowski 2013-02-21 21:58:11 UTC
(In reply to comment #0)
> The only option now available is the iframe hack described in the attached
> URL.

...or just not use the onload event at all!  I rarely use it, for good reason - it's always too late, and it's not just other scripts, it's everything!  

Often I'm halfway through filling out a form when the onload event causes a script to put focus back into the first field as I'm typing.  Infuriating!  Especially if it's the password I'm currently entering, and now my password is visible.  I just scream "Why are they using the onload event?!  Why would ANYBODY!!!", haha, really, I do!  Too often.

Of course the problem is the onload event can be delayed by any resources, not just scripts.

Whilst "nonblocking" sounds feasible, I don't think I will be persuaded to use it, because it still won't enable me to use the onload event satisfactorily.  

If the problem really is that the onload event could sometimes take forever, then best not to use it for anything critical to the user.

There is a DOMContentLoaded event which looks more appropriate.
Comment 7 Philip Tellis 2013-02-22 05:05:47 UTC
@Lee this isn't just to make sure the onload event handler fires on time.  Onload is also used as a proxy to determine when a page is ready from a statistics gathering perspective.  There are also users who won't start interacting with a page until the spinner stops spinning, which happens on onload.

Regarding DOMContentLoaded, it still doesn't guarantee that scripts loaded with the async attribute have finished downloading and executing, so you cannot depend on any of the functionality they provide.
Comment 8 Lee Kowalkowski 2013-02-22 10:32:09 UTC
(In reply to comment #7)
> Onload is also used as a proxy to determine when a page is ready from a
> statistics gathering perspective.

If gathering statistics isn't critical to the user, then using the onload event might be OK.  If gathering statistics for a page hit where the user didn't wait for onload is desirable, then don't wait for the onload event to gather the statistics.

Perhaps the fact that the user didn't wait for onload is a useful metric itself, perhaps the only useful statistic that can be gathered using the onload event, is the page load time.

> There are also users who won't start
> interacting with a page until the spinner stops spinning, which happens on
> onload.

I can't find any supporting evidence of the severity of this user phenomenon, no doubt there are some users with that habit, it's not an observation I've made very often, new users tend not to understand the spinner.  I know that young children don't do this, as soon as what they want is visible, they will try to use it.

I do remember it being necessary to wait until the page has finished loading when using some specific badly-implemented sites though (i.e. pages that don't even work properly if you interact with them too soon).  Perhaps such users are doing this from such experience, applying the behaviour as a rule to use all sites by, kind of like superstition.  For sure, the onload event is being used inappropriately on such sites.

Perhaps what we need in the HTML5 reference is a warning on the onload event that it is probably not as useful as the author might expect, given inherent uncertainty with networks.

> Regarding DOMContentLoaded, it still doesn't guarantee that scripts loaded
> with the async attribute have finished downloading and executing, so you
> cannot depend on any of the functionality they provide.

You should probably not use the async attribute for functionality the user will depend on though, and you should probably not have inter-script dependencies loading asynchronously without building a mechanism to allow the dependency to be late (e.g. polling).  

The async attribute is best suited for non-critical scripts (e.g. scripts that will progressively enhance something that is already functional).
Comment 9 Kyle Simpson 2013-02-24 03:29:23 UTC
I personally don't understand the need to avoid the `onload` blocking (and I happen to have plenty of experience in this area, as the author of LABjs script loader). I think the far bigger culprit is blocking the DOMContentLoaded event, and thankfully all the `async` and dynamic-script-element approaches take care of that part.

That having been said, even if I don't see the need for this, PLEASE do not piggyback on, and/or change, in any way, how `async` works (as I saw suggested in this thread). There are many, MANY script loaders, mine included, which rely on very specific behavior of `async`. It's a very tenuous and delicate balance we're currently in, where it barely works, but works just well enough.

On a side note, I doubt this request is going to get very far, because I have been trying to get another helpful change (script preloading: https://www.w3.org/Bugs/Public/show_bug.cgi?id=14194) made to the script loading behaviors of the browser for well over 2 years now, and keep getting stonewalled on it, mostly for the "just tell authors to do something different" excuse. I think the same fate is likely here, that they'll just say "why can't you just tell authors not to load stuff before `onload` if they don't want to block `onload`... wait until after it passes to start the loading."

I know, and you know, that's suboptimal compared to what you're asking for itself, but it's the same reasoning as what has blocked my requests for ages.
Comment 10 Yoav Weiss 2013-02-25 09:29:49 UTC
I support adding a mechanism that avoids blocking of the "onload" event by scripts, but as Kyle mentioned, this is not the only use-case that is not currently covered by `async` and `defer`.
I believe that another use-case can be "Loading scripts after onload" in order to load scripts of some added value, but ones which we don't want to intervene with the page's load time. While this can be easily done using scripts, having a declarative way to do that would be easier & cleaner. Also, in some cases, it avoids the use of inline scripts, which is complicated when using CSP.

Yet another use case may be loading of scripts according to `media`, since some scripts may be required only for certain layouts.

I suggest to gather up all the use-cases and see if we can solve all of them under a single solution.

AFAIK, the list includes:
* Loading scripts without blocking onload
* Loading scripts, but avoiding their execution
* Loading scripts after onload
* Loading scripts according to `media`

Are there any use-cases I'm missing?

Yoav
Comment 11 Honore Doktorr 2016-01-20 20:53:03 UTC
Quick status check: this was resolved FIXED a year ago, but there doesn’t seem to be any reference to it in the HTML 5.1 working draft.

If this proposal made it into a spec, does anyone have a link to it?

If the proposal was dropped, a WONTFIX resolution would prevent any confusion.  

from https://www.w3.org/TR/html51/semantics.html#the-script-element on Jan 20 2016

The async and defer attributes are boolean attributes that indicate how the script should be executed. The defer and async attributes must not be specified if the src attribute is not present.

There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed as soon as it is available, but without blocking further parsing of the page. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.

…

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behaviour instead of the blocking behaviour that is the default.
Comment 12 Philip Tellis 2016-01-21 00:12:06 UTC
the spec still doesn't mention at what point of time in the script's loading and execution the page's onload event fires.  Since that was part of the original bug, I'd say that this is not fixed.

Reopening.
Comment 13 Arron Eicholz 2016-04-20 19:19:14 UTC
HTML5.1 Bugzilla Bug Triage: 

This bug constitutes a request for a new feature of HTML. Our current guidelines, rather than track such requests as bugs or issues, is to create a proposal for the desired behavior, or at least a sketch of what is wanted (much of which is probably contained in this bug), and start the discussion/proposal in the WICG (https://www.w3.org/community/wicg/). As your idea gains interest and momentum, it may be brought back into HTML through the Intent to Migrate process (https://wicg.github.io/admin/intent-to-migrate.html).