[Fizz]: Unify preload queue (#27190)
Currently React attempts to prioritize certain preloads over others based on their type. This is at odds with allowing the user to control priority by ordering which calls are made first. There are some asset types that generally should just be prioritized first such as fonts since we don't know when fonts will be used and they either block display or may lead to fallback fonts being used. But for scripts and stylesheets we can emit them in the order received with other arbitrary preload types. We will eventually add support for emitting suspensey image preloads before other resources because these also block display however that implementation will look at which images are actually rendered rather than simply preloaded.
Josh Story committed
Aug 7, 2023 at 15:51 UTC
cb3404a0ccd8b5edf5d2b90bd844742090e38f42
2 files changed
+22
-58
packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
+10
-46
@@ -4250,20 +4250,8 @@ export function writePreamble(
4250
resources.scripts.forEach(flushResourceInPreamble, destination);
4251
resources.scripts.clear();
4252
4253
- resources.explicitStylesheetPreloads.forEach(
4254
- flushResourceInPreamble,
4255
- destination,
4256
- );
4257
- resources.explicitStylesheetPreloads.clear();
4258
-
4259
- resources.explicitScriptPreloads.forEach(
4260
- flushResourceInPreamble,
4261
- destination,
4262
- );
4263
- resources.explicitScriptPreloads.clear();
4264
-
4265
- resources.explicitOtherPreloads.forEach(flushResourceInPreamble, destination);
4266
- resources.explicitOtherPreloads.clear();
4253
+ resources.explicitPreloads.forEach(flushResourceInPreamble, destination);
4254
+ resources.explicitPreloads.clear();
4255
4256
// Write embedding preloadChunks
4257
const preloadChunks = responseState.preloadChunks;
@@ -4330,14 +4318,8 @@ export function writeHoistables(
4318
resources.scripts.forEach(flushResourceLate, destination);
4319
resources.scripts.clear();
4320
4333
- resources.explicitStylesheetPreloads.forEach(flushResourceLate, destination);
4334
- resources.explicitStylesheetPreloads.clear();
4335
-
4336
- resources.explicitScriptPreloads.forEach(flushResourceLate, destination);
4337
- resources.explicitScriptPreloads.clear();
4338
-
4339
- resources.explicitOtherPreloads.forEach(flushResourceLate, destination);
4340
- resources.explicitOtherPreloads.clear();
4321
+ resources.explicitPreloads.forEach(flushResourceLate, destination);
4322
+ resources.explicitPreloads.clear();
4323
4324
// Write embedding preloadChunks
4325
const preloadChunks = responseState.preloadChunks;
@@ -4882,10 +4864,7 @@ export type Resources = {
4864
stylePrecedences: Map<string, StyleTagResource>,
4865
bootstrapScripts: Set<PreloadResource>,
4866
scripts: Set<ScriptResource>,
4885
- explicitStylesheetPreloads: Set<PreloadResource>,
4886
- // explicitImagePreloads: Set<PreloadResource>,
4887
- explicitScriptPreloads: Set<PreloadResource>,
4888
- explicitOtherPreloads: Set<PreloadResource>,
4867
+ explicitPreloads: Set<PreloadResource>,
4868
4869
// Module-global-like reference for current boundary resources
4870
boundaryResources: ?BoundaryResources,
@@ -4909,10 +4888,7 @@ export function createResources(): Resources {
4888
stylePrecedences: new Map(),
4889
bootstrapScripts: new Set(),
4890
scripts: new Set(),
4912
- explicitStylesheetPreloads: new Set(),
4913
- // explicitImagePreloads: new Set(),
4914
- explicitScriptPreloads: new Set(),
4915
- explicitOtherPreloads: new Set(),
4891
+ explicitPreloads: new Set(),
4892
4893
// like a module global for currently rendering boundary
4894
boundaryResources: null,
@@ -5199,22 +5175,10 @@ export function preload(href: string, options: PreloadOptions) {
5175
5176
pushLinkImpl(resource.chunks, resource.props);
5177
}
5202
- switch (as) {
5203
- case 'font': {
5204
- resources.fontPreloads.add(resource);
5205
- break;
5206
- }
5207
- case 'style': {
5208
- resources.explicitStylesheetPreloads.add(resource);
5209
- break;
5210
- }
5211
- case 'script': {
5212
- resources.explicitScriptPreloads.add(resource);
5213
- break;
5214
- }
5215
- default: {
5216
- resources.explicitOtherPreloads.add(resource);
5217
- }
5178
+ if (as === 'font') {
5179
+ resources.fontPreloads.add(resource);
5180
+ } else {
5181
+ resources.explicitPreloads.add(resource);
5182
}
5183
flushResources(request);
5184
}
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+12
-12
@@ -4131,6 +4131,12 @@ body {
4131
expect(getMeaningfulChildren(document)).toEqual(
4132
<html>
4133
<head>
4134
+ <link
4135
+ rel="preload"
4136
+ as="script"
4137
+ href="highserver"
4138
+ fetchpriority="high"
4139
+ />
4140
<link
4141
rel="preload"
4142
as="style"
@@ -4143,12 +4149,6 @@ body {
4149
href="autoserver"
4150
fetchpriority="auto"
4151
/>
4146
- <link
4147
- rel="preload"
4148
- as="script"
4149
- href="highserver"
4150
- fetchpriority="high"
4151
- />
4152
</head>
4153
<body>hello</body>
4154
</html>,
@@ -4166,6 +4166,12 @@ body {
4166
expect(getMeaningfulChildren(document)).toEqual(
4167
<html>
4168
<head>
4169
+ <link
4170
+ rel="preload"
4171
+ as="script"
4172
+ href="highserver"
4173
+ fetchpriority="high"
4174
+ />
4175
<link
4176
rel="preload"
4177
as="style"
@@ -4178,12 +4184,6 @@ body {
4184
href="autoserver"
4185
fetchpriority="auto"
4186
/>
4181
- <link
4182
- rel="preload"
4183
- as="script"
4184
- href="highserver"
4185
- fetchpriority="high"
4186
- />
4187
<link
4188
rel="preload"
4189
as="script"