- From: Garrett Smith <dhtmlkitchen@gmail.com>
- Date: Mon, 9 Feb 2009 18:15:32 -0800
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