[whatwg] defer on style, depends

On Mon, Feb 9, 2009 at 11:54 AM, Boris Zbarsky <bzbarsky at mit.edu> wrote:
> Garrett Smith wrote:
>>
>> There are two/three issues.
>> 1) want to load stylesheets without having scripts block
>
> Already doable for alternate stylesheets, right?
>

An html document could contain an alternate stylesheet, intended for a
script to change the stylesheet from "alternate".

That would make the code less straightforward. It is going to be
harder for a fresh pair of eyes to understand what is going on.

> I assume the use case is a script that wants to modify the DOM immediately
> but doesn't depend on any styling information?  That's a property of the
> script, not the stylesheet, correct?
>

What do you propose?

A "nodepends" attribute for a script element?

Lets go over what I want the browser to do:

In general, I want better declarative control over loading external
resources. The solution(s) should not cause compatibility problems
with existing browsers (because I have to support IE6 and Firefox 2).

I want the browser to be able to load and run a script without being
in the position of trying to determine if it should wait for
stylesheet data to complete. I've noticed these things hang.

I also want to be able to load and run a script, without having to
resort to a clunky API (createElement('script')).

To declare the script to load and run immediately after the
stylesheets (without depending on the style information), Ian
suggested that I put the script first in the head and use defer.

That will have a negative affect on performance in all browsers that
support defer and the browsers that do not support defer.

In browsers that do not support defer, the scripts must be loaded
before subsequent content is loaded. The scripts will block content
from rendering below. Scripts will also prevent download of linked
stylesheets that appear after in the source. This type of design would
also have a negative effect on browsers that do *not* support defer
because it means that the scripts appear first, before any linked
stylesheets, and cannot be included at the bottom (which is common to
do for performance reasons).

In browsers that do support defer, the script would run *after* the
document parsed, and that would occur after the stylesheet loaded.

Example:
http://dhtmlkitchen.com/jstest/block/link-defer-top.html

We can see that the deferred "alert" external script will run first in
browsers that ignore defer. In browsers that do not ignore defer, it
will run last, after the stylesheet is loaded. Including a deferred
script first will result in an inconsistent execution of that script.
It would requires= a very flexible program design (that may result in
error if not very careful) and for absolutely no benefit.

The result would be bad for performance either way. This was Ian's
advice. It is impractical, error prone, and bad for performance. That
is horrible advice.

>> 2) want to load stylesheets later, (infoPanel example)
>
> Not sure what this example is, or why this is insufficienty served by, say,
> putting the <link> at the end of the HTML (assuming HTML allowed that, of
> course).
>

Are you proposing HTML allow that?

>> 3) (2), but want to make sure the stylesheet is loaded before the script
>> runs.
>
>> (1) <link independent ..> would address the problem.
>
> Independent of what?  In case (1) it's the script that doesn't depend on the
> stylesheet, as far as I can see.  The stylesheet just exists.
>

The script could declare whether it needs such resource by its
"depends=" attribute. However, browsers today delay (some) scripts
from running. Scripts depend on stylesheets; content depends on
scripts and stylesheets. Content can contain more scripts. Omitting
depends for scripts could not possibly solve the problem for browsers
today (because they already depend on stylesheets).

An "independent" attribute on a link says that a browser does not need
to wait for that resource to finish loading before it loads other
resources (like loading a script). When the parser parses that
"independent" attribute, it sets a flag for the browser go ahead and
download and run any subsequent script.

A "nodepends" type attribute on a script would work, too. I like that
idea, though it does mean the browser has to do some lookahead (then
again, apparently they already do).

>> Example 1:
>> <head><title></title>
>> <link independent type="text/css"  ...>
>> <script...></script>
>> I want the browser to:
>> 1) load my stylesheet and then immediately begin to load script in
>> parallel.
>
> That's exactly what Gecko does in this case, for what it's worth.  It will
> load the script in parallel, but won't _execute_ the script until the
> non-alternate stylesheet has loaded.
>

For a script in the head, that is what Gecko and Webkit will do.
However, external resources such as SCRIPT or IMG that appear in the
BODY will not get requested by the browser until the page content
renders. That is actually a good argument for *not* moving scripts to
before the closing body tag.

In both cases (head script or body script), the browser will not
execute the script until the stylesheet is downloaded. It won't render
content that occurs after the script until the script is executed.

So what we have here is a daisy chain. Content depends on Script
depends on Style. That is very crude order of affairs and offers the
developer little control over load order.

For example:
http://localhost/jstest/block/link-defer.html

In Safari 3.1,content is rendered after 5 seconds. After 5 seconds, I see:
contentLoaded: 2
onloadFired: 5008

In this case, I want the script to in the head to download and execute
without waiting for the css.

to fulfill example 2, I would defer the stylesheet, and declare the
script at the end depends on it. Before that script could run, the
stylesheet would need to be loaded. Since the linked stylesheet is
deferred, the body content would render and not be blocked by the
linked stylesheet loading. I don't know if it would be possible to
optimize reflow for that, or if it would be possible to "scope" the
stylesheet somehow.

>> Example 2
>> <head><title></title>
>> <link defer type="text/css" id="lateBoundCSS" ...>
>
> What is the use case for such CSS, exactly?
>

A deferred stylesheet could be used for styling hidden elements that
will be shown, or components that are created in javascript.

This would allow the browser to render content before the process of
applying that style information.

Question: When the stylesheet is eventually applied, could the reflow
be optimized for performance?

>> 1) defer my linked stylesheet id="lateBoundCSS" until content is rendered
>> 2) render content
>> 3) upon encountering the deferred script, check the depends
>> 4) upon finding Result(3) is "lateBoundCSS", wait for that resource to
>> finish load before running.
>
> Is this a common use case?  Would it be sufficient to address it via a load
> handler on <link> so that one could build whatever dependency or ordering
> setup one wants?
>

That would put the css information in the script and make the document
source harder to understand. It clutters up the script and is even
messier than adding a "nodepends" attribute.

>> The infoPanel script needs the infoPanel.css stylesheet,
>> id="lateBoundCSS". The css is only related to that script, it is
>> useless otherwise.
>
> You mean the CSS is not actually used to style the document?
>

It is used to style the infoPanels. These are hidden.

For example:
http://www.netflix.com/Search?v1=boris

The Netflix page features a popup div (that code is definitely not to
be taken as a example of quality engineering). That page could
potentially take advantage of loading the "popup" div's css until
after the script that calls it had loaded and run.

Anything that is an enhancement of the original content, such as a
hidden "search suggest" div, "tooltip" divs, or content loaded via XHR
might want to load and apply external CSS later.

In this case, the initial page layout is not affected by the linked
stylesheet. Before the script executes, the deferred linked stylesheet
must be rendered.

A deferred a stylesheet would load after the page loads, but if a
script declared "depends=", the stylesheet resource would have to be
complete before the script would run.

Garrett

> -Boris
>
>

Received on Monday, 9 February 2009 18:15:32 UTC