-
Notifications
You must be signed in to change notification settings - Fork 51k
[Float][Fiber] Assume stylesheets in document are already loaded #29811
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
When we made stylesheets suspend even during high priority updates we exposed a bug in the loading tracking of stylesheets that are loaded as part of the preamble. This allowed these stylesheets to put suspense boundaries into fallback mode more often than expected because cases where a stylesheet was server rendered could now cause a fallback to trigger which was never intended to happen. This fix updates resource construction to evaluate whether the instance exists in the DOM prior to construction and if so marks the resource as loaded and inserted. One ambiguity that needed to be solved still is how to tell whether a stylesheet rendered as part of a late Suspense boundary reveal is already loaded. I updated the instruction to clear out the loading promise after successfully loading. This is useful because later if we encounter this same resource again we can avoid the microtask if it is already loaded. It also means that we can concretely understand that if a stylesheet is in the DOM without this marker then it must have loaded (or errored) already.
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,11 @@ export function completeBoundaryWithStyles( | |
| const dependencies = []; | ||
| let href, precedence, attr, loadingState, resourceEl, media; | ||
|
|
||
| function cleanupWith(cb) { | ||
| this['_p'] = null; | ||
| cb(); | ||
| } | ||
|
|
||
| // Sheets Mode | ||
| let sheetMode = true; | ||
| while (true) { | ||
|
|
@@ -82,18 +87,14 @@ export function completeBoundaryWithStyles( | |
| resourceEl.setAttribute(attr, stylesheetDescriptor[j++]); | ||
| } | ||
| loadingState = resourceEl['_p'] = new Promise((resolve, reject) => { | ||
| resourceEl.onload = resolve; | ||
| resourceEl.onerror = reject; | ||
| resourceEl.onload = cleanupWith.bind(resourceEl, resolve); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be smaller to just inline the function like an arrow function. We probably compile them out but if we ever stop.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need bind b/c i mutate the resourceEl the binding. not doing so leads to closure spitting out very large code b/c it gives the variable some enormous loop name |
||
| resourceEl.onerror = cleanupWith.bind(resourceEl, reject); | ||
| }); | ||
| // Save this resource element so we can bailout if it is used again | ||
| resourceMap.set(href, resourceEl); | ||
| } | ||
| media = resourceEl.getAttribute('media'); | ||
| if ( | ||
| loadingState && | ||
| loadingState['s'] !== 'l' && | ||
| (!media || window['matchMedia'](media).matches) | ||
| ) { | ||
| if (loadingState && (!media || window['matchMedia'](media).matches)) { | ||
| dependencies.push(loadingState); | ||
| } | ||
| if (avoidInsert) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this check removed? If there is an existing style sheet why would we preload it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only call this function in one place and I changed it to gate the call on the instance not existing so we don't need to duplicate the check here