Re: [HTML Imports]: Sync, async, -ish?

Thanks Elliott! I'll admit I don't (yet) have a deep understanding of
imports/web components so I'm not surprised to have overlooked things.
Thank you for clarifying these areas for me.

So to summarize:
* imports should not block parsing/DOM tree construction
* imports should block rendering (e.g. render tree construction), just like
stylesheets
* we should add support for loading stylesheets and imports without
blocking rendering, so developers can load imports that they'll use in the
future without blocking rendering of other content on their load completing
* Elliott proposes adding support for an 'async' tag. <link async>
indicates that the load of that stylesheet/import must not block rendering.
This is useful for both imports and stylesheets (more on this below)


On Tue, Dec 3, 2013 at 8:37 PM, Elliott Sprehn <esprehn@chromium.org> wrote:

>
> On Tue, Dec 3, 2013 at 2:22 PM, Bryan McQuade <bmcquade@google.com> wrote:
>
>> Second question: should *rendering* of page content block on the load of
>> <link rel=import>
>>
>> Steve Souders wrote another nice post about this topic:
>> http://www.stevesouders.com/blog/2013/11/26/performance-and-custom-elements/which I recommend reading (read the comments too).
>>
>> We should start by looking to how the web platform behaves today. All
>> browsers I am aware of block rendering on the load of pending stylesheets.
>> Note that blocking rendering (blocking of render tree construction and
>> painting content to the screen) is different from blocking parsing.
>> Browsers do not block HTML parsing (DOM construction) on stylesheets. Nor
>> should they block DOM construction on loading of <link rel=import>s.
>>
>>
> Correct. Imports are even better than the main document though.
> document.write doesn't work, and we allow the parser to "run ahead" and not
> block on <script> inside an import. That means putting <script
> src="slow-resource.js"></script> in your import will not slow down the
> parser as it processes the import tree. It'll continue building the
> documents of imports while the resource loads.
>

Great!


>
>
>> The reason to block rendering while a custom element's load is pending is
>> to prevent a flash of unstyled content/reflow of content on the page. At a
>> high level:
>>
>
> We are not blocking rendering on custom elements. We're waiting for a
> critical resource to load because it may contain <style> or <script>.
>

Just to clarify, do you mean not blocking rendering (e.g. render tree
construction) or do you mean not blocking parsing (i.e. dom tree
construction)? It's clear that we don't block dom tree construction but it
seems to be up for debate (and perhaps not spec'd anywhere) whether imports
block render tree construction (or whatever equivalent to render tree
construction exists in other browsers). Stylesheets block render tree
construction to prevent a FOUC. Given that imports may include styles, it
seems sensible that they would behave like styles and also block
rendering/render tree construction (unless they are marked as async, as you
suggest below).


>
>
>> 1. if there are no custom elements in the DOM, [...]
>> 2. if there are custom elements in the DOM [...]
>>
>
> We should not be focusing on custom elements here. Imports and custom
> elements are separate but related features and neither depends on the
> other. Lots of things could be inside the import. Custom elements don't
> block anything.
>

Thank you - I has assumed imports were only used for custom elements. I
understand now that they're more generic and powerful. Given this, I agree
- we should not focus on custom elements.


>
>
>> However, if the positioning of the custom element changes as a result of
>> its being upgraded, i.e. its x/y/width/height changes, [...]
>>
>
>> So how do we strike a balance between fast rendering and avoiding
>> reflow/content moving around on the screen? In the case of custom elements
>> there are a few things that browsers can do:
>>
>>  1. if there are no custom elements in the DOM, then even if a load of a
>> custom element import is pending, then there is no reason to block
>> rendering of the rest of the page, since the custom element's load can't
>> impact the styling of content in the DOM.
>>
>
> This is not correct. Imports are not just for custom elements, they're a
> generic system for importing "stuff". You can put a <style> in the import
> and it will apply to the main page.
>

Agree, thanks for correcting me.


>
>
>> 2. if there are custom elements in the DOM and a custom element import's
>> load is pending, *and* it can be determined by the rendering engine that
>> the load/upgrade of that element will not cause its *position* to change
>> (e.g. that element has a "style="width:x;height:y;" attribute, or a
>> style="display:none", etc - we'll have to overlook !important styles for
>> this...) then we should not block rendering of the rest of the page, since
>> the content other than the custom element will not change position as a
>> result of the custom element loading.
>>
>
>
This is a heuristic that browsers could apply, yes. I don't believe there
> is a spec for browsers waiting to paint on remote stylesheets though, in
> fact they probably should paint if the sheet is taking forever to load.
>

I believe you are correct - I'm not aware that render blocking behavior is
spec'd anywhere. Perhaps it should be. I think you are correct that most
browsers will time out a stylesheet load in other contexts (e.g. when
blocking script execution:
http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#a-style-sheet-that-is-blocking-scripts)
and this likely will time out blocking of render tree construction as well.


>
>
>>
>> However, if there are custom elements in the DOM whose position isn't
>> specified in an inline style, and a custom element import load is pending,
>> then rendering (not parsing!) should block until that custom element has
>> finished loading, to prevent a FOUC/reflow.
>>
>
> The parser does not block on rel="import" and document.write() is disabled
> down there for this reason. There's no predictability for where it's going
> to write since the parser could be anywhere when your import finally loads.
>

To clarify, blocking parsing and blocking rendering are two different
things. Imports do not (and should not) block parsing (dom tree
construction). I'm more interested in whether they should block rendering
(e.g. render tree construction).


>
>
>>
>> If we take this approach, then developers have two ways to prevent the
>> load of custom elements from blocking rendering:
>> ...
>>
>
>
>> So, I propose that, similar to pending stylesheets, the load of custom
>> elements should block rendering
>>
>
> We can't block anything on custom elements, but we certainly can on
> imports. I think we should as well and then add an async attribute to allow
> an author to declare the import as non-critical.
>

Right. Just to clarify, when we say imports should block, we mean imports
should block rendering (e.g. render tree construction) rather than parsing
(i.e. dom tree construction).

I agree that there is a need for an async attribute on <link> tags. It
would be useful for stylesheets as well. It's currently very difficult to
load a stylesheet without blocking the renderer. In many cases, my web app
may need a very small amount of CSS to render the initial view, and a bunch
of additional CSS to style content that shows up as the user interacts with
it. Ideally I'd be able to say "here's my render blocking CSS - it's small
and maybe inlined - don't render until you've processed it" and "here's
some other CSS that I'll need later. please fetch it and apply it as it
becomes available, and let me listen to a load event for it, but don't
block rendering on it". This allows me to render the initial view more
quickly than if I block rendering on all of my styles. 'async' feels like
the right way to provide this. Note that there is a proposal for a
'lazyload' attribute which is similar (
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourcePriorities/Overview.html#attr-lazyload),
but I'm inclined to use 'async' for this purpose as it more directly states
the intent: don't block (rather than lazyload, which indicates that the
resource is low priority).

However, in the case of <link>, async means something slightly different
from the case of <script>. For <script>, async means it does not block
parsing (dom tree construction). For <link> async would mean that it 'must
not' block rendering (e.g. render tree construction).


>
>
>> . With custom elements, however, we can be a bit smarter than with
>> stylesheets: rendering should block only in cases where the upgrade of a
>> custom element in the DOM might cause a reflow, moving other page content
>> on the screen.
>>
>
> There is no way to do this. A document might contain custom elements that
> are not upgraded until hours later when the author decides to call
> document.register. In general imports are separate from custom elements as
> well, we block on them because they're effectively a set of packaged
> <style> and <script> blocks which would have blocked painting had they been
> inside the main document.
>

Makes sense - I'm still learning. Thank you for taking the time to reply
and correct me on this. :)


>
> - E
>

Received on Wednesday, 4 December 2013 15:38:52 UTC