w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
332 stars 56 forks source link

Review request on `blocking=render` attribute for scripts and stylesheets #727

Closed xiaochengh closed 1 year ago

xiaochengh commented 2 years ago

Braw mornin' TAG!

Edit: This feature now affects scripts and stylesheets only. The behavior on preloads have been removed due to whatwg/html#7896.

I'm requesting a TAG review of blocking=render attribute for scripts and stylesheets and link resources.

All current browsers already have a render-blocking mechanism: after a navigation, the user agent will not render any pixel to the screen before stylesheets and synchronous scripts are loaded and evaluated (or a UA-defined timeout is reached), to prevent a Flash of Unstyled Content and ensure that critical scripts are evaluated. We extend this idea by introducing the blocking=render attribute, which can explicitly mark other resources (script, style and link of types modulepreload, preload and stylesheet) as render-blocking, so that a flash of undesired contents can be prevented in more use cases (see explainer).

Further details:

We'd prefer the TAG provide feedback as (please delete all but the desired option):

💬 leave review feedback as a comment in this issue and @-notify xiaochengh@

LeaVerou commented 2 years ago

How does the corresponding IDL attribute work? Would element.blocking === "render" be true for elements that are render-blocking by default?

xiaochengh commented 2 years ago

No. element.blocking simply reflects the content attribute.

plinss commented 2 years ago

@cynthia and I took a look at this this week and we have some concerns about what user need this is actually serving?

The explainer list a uses case of wanting to block on font loading, which can already be controlled via CSS, is generally considered a bad thing to do by the CSSWG, and usually leads to a very bad user experience. The other use cases seem somewhat questionable.

This feature also goes against one of the TAG's design principles. Is there really a need to add more render blocking?

xiaochengh commented 2 years ago

Thanks for the review! My response is as follows:

The explainer list a uses case of wanting to block on font loading, which can already be controlled via CSS

CSS font-display descriptor cannot control render-blocking. It only leaves an empty space for the text that uses the web font, and still renders other contents. Since the empty space is measured using a fallback font, its dimensions can still change when the actual web font is swapped in, causing a layout shift. There is a rich literature about this, to name a few:

The other use cases seem somewhat questionable.

I believe the other use cases are also as strong.

For the second use case (script-inserted style & script): In practice many web developers struggle to properly pre-process their blocking style sheets and scripts, which is one reason CLS is quite common. This is especially true for individual, educational or indie developers, who don't have the resources to build & maintain fancy server-side templating and serving systems. The linked educational example is one such example, which is served from raw sources without any build step, has many constituent pages, and a loader script to avoid duplication of common resources (& corresponding mistakes) across these pages. There is no advantage at all to the multi-render progressive loading for this site, it just looks jarring and ugly. blocking=render solves it elegantly.

For the third use case (async script), blocking=render provides immediate improvements to client-side A/B testing. We need to ensure that the test config script (which may, e.g., restyle certain elements) is run before rendering starts. Otherwise, the user may interact with an unconfigured page, making any subsequent measurements invalid. Current approaches either manually hide the document with JS, or do nothing and risk having invalid results. Also @alexnj to elaborate.

This feature also goes against one of the TAG's design principles.

The principle allows adding such features “only in cases when the overall user experience is improved”, which I believe is exactly the case for blocking=render. In all the use cases, blocking=render prevents a flash of unstyled content, which the principles already deemed “undesirable”.

plinss commented 2 years ago

Bumping this issue until Sangwhan is available, IIRC some of his concerns were about how this feature can be abused (either intentionally or unintentionally) causing significant delays for users on slow connections or who need to download very large resources (like CKJ fonts) that the page author may not take into consideration.

xiaochengh commented 2 years ago

Regarding the concern:

  1. Since there are scenarios where this feature seems necessary, but also other scenarios where misusing the feature leads to a bad performance, we recommend web authors to use it with caution and only when necessary. It's also no more (or less) of a rendering footgun than putting a script or stylesheet in the head. If that resource has a problem then you have a SPOF but it's not particularly extraordinary in the risk.

  2. The risk of blocking=render might also be smaller than traditional scripts and stylesheets. Web authors can, e.g., set a timeout that removes the attribute, to manually unblock rendering if it takes too long to load. This is not achievable for traditional scripts and stylesheets.

xiaochengh commented 2 years ago

Hi TAG,

Due to whatwg/html#7896, we have removed blocking=render on preload. As a result, now it only affects scripts and stylesheets, which is a small extension since these elements can already be implicitly render-blocking.

yoavweiss commented 2 years ago

Friendly ping, as this now has a pending intent :)

plinss commented 2 years ago

We're OK with adding this to script tags as that usage can be interpreted as adding the ability to add async processing to already blocking scripts, so this is an enhancement.

However, we still have concerns about adding additional blocking to stylesheets, particularly for the purpose of blocking on font loading (and as @cynthia mentioned, CKJ fonts can be large and connections can be slow). In the past webkit blocked for up to 30 seconds on webfont loading and the user experience was horrible. CSS added mechanisms to control rendering with webfonts, adding an additional mechanism to achieve this seems bad.

xiaochengh commented 2 years ago

Thanks for the review!

However, we still have concerns about adding additional blocking to stylesheets, particularly for the purpose of blocking on font loading

Adding this to stylesheets will not block page rendering on web font loading. It will only block on critical subresources, which is currently underdefined, but so far no implementation includes web fonts as critical subresources.

We are indeed pursuing CSS-based approaches to for rendering control with web fonts, which however should be orthogonal to this blocking=render feature.

plinss commented 1 year ago

Thanks for the response, we're going to close this review as satisfied, but we still have some concerns. Mainly, new mechanisms to block rendering need to be used very carefully by developers or they can easily fall into traps that result in a worse user experience (e.g. not realizing how slow user's devices and connections may be in the wild), so developers need to tread very carefully when using this and the additional complexity needs to be carefully explained.

Furthermore, some of the use cases seem to be replicating existing capabilities that would be better handled declaratively. For example, using script to inject links to stylesheets in certain situations should rather be handled by CSS mechanisms like feature and media queries so the UA can scan for preloading opportunities, handling is not gated by script execution, etc.

We do like the possible future extensions of being able to relax blocking in situation that are currently blocking.