Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update document-render-blocking.md to include more options #214

Merged
merged 4 commits into from
Aug 26, 2023

Conversation

khushalsagar
Copy link
Collaborator

No description provided.

document-render-blocking.md Outdated Show resolved Hide resolved
document-render-blocking.md Outdated Show resolved Hide resolved
- Lower CLS: A stable layout of the DOM depends on both parsing the requisite DOM nodes and fetching relevant stylesheets. Without control over parsing, its likely that the browser does multiple renders with layout shifts as more of the DOM is parsed.
Authors will sometimes use `display: none` or `opacity: 0` to hide the whole Document to prevent this.

- Atomic rendering of semantic elements: A UI widget built using a DOM sub-tree might not make sense to render partially. Consider a menu where only half the buttons show up on first render. Authors could mark sections in the Document which semantically render one widget so the browser doesn't yield midway through parsing one widget.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like a parser may have some context here already, like try not yielding between siblings, or something like, but yeah your point that developers may want to control this makes sense


- Atomic rendering of semantic elements: A UI widget built using a DOM sub-tree might not make sense to render partially. Consider a menu where only half the buttons show up on first render. Authors could mark sections in the Document which semantically render one widget so the browser doesn't yield midway through parsing one widget.

- Optimal Yielding: The browser may yield later than was necessary leading to rendering more what's required for above the fold content. A developer hint about a yielding trigger could imply the first frame has less DOM to parse, style, and layout. Browsers can optimize paint to be limited to onscreen content but the prior stages are executed over the entire DOM.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'm parsing the second and third sentences well.

Do you mean to say that a developer can provide a better hint resulting in less of the DOM tree to parse, style, and layout?

And also, "prior stages" you mean style & layout?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to say that a developer can provide a better hint resulting in less of the DOM tree to parse, style, and layout?

Yeah, less to parse, style and layout for first frame resulting in better FCP.

And also, "prior stages" you mean style & layout?

Yes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe rephrase somehow <_<

document-render-blocking.md Outdated Show resolved Hide resolved

## Meta Tag with Blocking ElementIds

Add a new meta tag with the name `blocking-elements` and `content` attribute set to the list of [element IDs](https://dom.spec.whatwg.org/#concept-id) which must be parsed before rendering. `*` is a special keyword which implies every ID should be blocking.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this limited to parsing the shallow element, or does this include subresources? I'm thinking specifically if I have an img here, what are we blocked on exactly

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its the shallow element, not subresources.


Add a new meta tag with the name `blocking-elements` and `content` attribute set to the list of [element IDs](https://dom.spec.whatwg.org/#concept-id) which must be parsed before rendering. `*` is a special keyword which implies every ID should be blocking.

Each Document has a render-blocking-until-parsed element ids set, initially empty. A Document is [render-blocked](https://html.spec.whatwg.org/#render-blocked) if this set is non-empty.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or *? If it's a set of ids, and I have no ids, then maybe we need a special carve out for *

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried doing that, lmk if I missed anything.

document-render-blocking.md Outdated Show resolved Hide resolved

- Each time an element's ID value changes, the browser checks if the set of elements which have been completely parsed (i.e. the end tag has been parsed) include all IDs in the render-blocking-until-parsed element ids set. If yes, the render-blocking-until-parsed element ids set is cleared.

The pro of this approach is that its easier to block on a specific set of elements, which makes it more likely that authors will consider partial blocking. The con is new syntax which requires defining subtle interactions (like script changing element IDs after parsing).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to write a simple js library that has some ergonomic functions like "didParse(foo)" that does all of this.

The problem with removing one element from a list of comma separated values is that you need to parse the list, find the value, remove it, and join the list back up, and set it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with removing one element from a list of comma separated values is that you need to parse the list, find the value, remove it, and join the list back up, and set it

I didn't follow the use-case you're worried about. Ideally authors will set the list once (in ) and won't change it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, the list wouldn't be changed, it's the UA that tracks it


The pro of this approach is that its easier to block on a specific set of elements, which makes it more likely that authors will consider partial blocking. The con is new syntax which requires defining subtle interactions (like script changing element IDs after parsing).

### Including Blocking Tokens
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also note that a typo in this list would cause the parser to block on the whole document (waiting for the non-existent id), but in that case we can throw an error to the console

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Collaborator

@vmpstr vmpstr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm


- Atomic rendering of semantic elements: A UI widget built using a DOM sub-tree might not make sense to render partially. Consider a menu where only half the buttons show up on first render. Authors could mark sections in the Document which semantically render one widget so the browser doesn't yield midway through parsing one widget.

- Optimal Yielding: The browser may yield later than was necessary leading to rendering more what's required for above the fold content. A developer hint about a yielding trigger could imply the first frame has less DOM to parse, style, and layout. Browsers can optimize paint to be limited to onscreen content but the prior stages are executed over the entire DOM.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe rephrase somehow <_<

@vmpstr vmpstr merged commit 9ddc4b6 into main Aug 26, 2023

The above requires the new Document to know about the old Document's visual state when the transition started. This can't be done trivially today. The Navigation API provides the list of [entries](https://developer.mozilla.org/en-US/docs/Web/API/Navigation/entries) and the [current entry](https://developer.mozilla.org/en-US/docs/Web/API/Navigation/currentEntry) but there is no notion of a "previous entry" before the current entry was committed.

[html/256](https://github.com/WICG/navigation-api/issues/256) addresses this. The examples in this proposal rely on the API proposed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would that solve the scroll state? Is that somehow accessible on the entry itself?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that somehow accessible on the entry itself?

No, this will have to be manual. Authors can use IntersectionObserver to track whether an element is visible and cache that information on the Document's NavigationHistoryEntry via state in updateCurrentEntry.

This proposal is need to look up the previous Document's NavigationHistoryEntry. You can then query the information above which was cached by the old Document using getState.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants