Skip to content

Commit 5a690dc

Browse files
committed
support fetchPriority as an option for ReactDOM.preload() and ReactDOM.preinit()
1 parent e1e68b9 commit 5a690dc

File tree

4 files changed

+211
-2
lines changed

4 files changed

+211
-2
lines changed

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,6 +2173,7 @@ type PreloadOptions = {
21732173
crossOrigin?: string,
21742174
integrity?: string,
21752175
type?: string,
2176+
fetchPriority?: 'high' | 'low' | 'auto',
21762177
};
21772178
function preload(href: string, options: PreloadOptions) {
21782179
if (!enableFloat) {
@@ -2245,6 +2246,7 @@ function preloadPropsFromPreloadOptions(
22452246
crossOrigin: as === 'font' ? '' : options.crossOrigin,
22462247
integrity: options.integrity,
22472248
type: options.type,
2249+
fetchPriority: options.fetchPriority,
22482250
};
22492251
}
22502252
@@ -2254,6 +2256,7 @@ type PreinitOptions = {
22542256
crossOrigin?: string,
22552257
integrity?: string,
22562258
nonce?: string,
2259+
fetchPriority?: 'high' | 'low' | 'auto',
22572260
};
22582261
function preinit(href: string, options: PreinitOptions) {
22592262
if (!enableFloat) {
@@ -2395,6 +2398,7 @@ function stylesheetPropsFromPreinitOptions(
23952398
'data-precedence': precedence,
23962399
crossOrigin: options.crossOrigin,
23972400
integrity: options.integrity,
2401+
fetchPriority: options.fetchPriority,
23982402
};
23992403
}
24002404
@@ -2408,6 +2412,7 @@ function scriptPropsFromPreinitOptions(
24082412
crossOrigin: options.crossOrigin,
24092413
integrity: options.integrity,
24102414
nonce: options.nonce,
2415+
fetchPriority: options.fetchPriority,
24112416
};
24122417
}
24132418

packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5093,6 +5093,7 @@ type PreloadOptions = {
50935093
crossOrigin?: string,
50945094
integrity?: string,
50955095
type?: string,
5096+
fetchPriority?: 'high' | 'low' | 'auto',
50965097
};
50975098
export function preload(href: string, options: PreloadOptions) {
50985099
if (!enableFloat) {
@@ -5238,6 +5239,7 @@ type PreinitOptions = {
52385239
crossOrigin?: string,
52395240
integrity?: string,
52405241
nonce?: string,
5242+
fetchPriority?: 'high' | 'low' | 'auto',
52415243
};
52425244
function preinit(href: string, options: PreinitOptions): void {
52435245
if (!enableFloat) {
@@ -5501,6 +5503,7 @@ function preloadPropsFromPreloadOptions(
55015503
crossOrigin: as === 'font' ? '' : options.crossOrigin,
55025504
integrity: options.integrity,
55035505
type: options.type,
5506+
fetchPriority: options.fetchPriority,
55045507
};
55055508
}
55065509

@@ -5542,6 +5545,7 @@ function stylesheetPropsFromPreinitOptions(
55425545
'data-precedence': precedence,
55435546
crossOrigin: options.crossOrigin,
55445547
integrity: options.integrity,
5548+
fetchPriority: options.fetchPriority,
55455549
};
55465550
}
55475551

@@ -5573,6 +5577,7 @@ function scriptPropsFromPreinitOptions(
55735577
crossOrigin: options.crossOrigin,
55745578
integrity: options.integrity,
55755579
nonce: options.nonce,
5580+
fetchPriority: options.fetchPriority,
55765581
};
55775582
}
55785583

packages/react-dom/src/ReactDOMDispatcher.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ export type PreloadOptions = {
1414
crossOrigin?: string,
1515
integrity?: string,
1616
type?: string,
17+
fetchPriority?: 'high' | 'low' | 'auto',
1718
};
1819
export type PreinitOptions = {
1920
as: string,
2021
precedence?: string,
2122
crossOrigin?: string,
2223
integrity?: string,
2324
nonce?: string,
25+
fetchPriority?: 'high' | 'low' | 'auto',
2426
};
2527

2628
export type HostDispatcher = {

packages/react-dom/src/__tests__/ReactDOMFloat-test.js

Lines changed: 199 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,6 +3789,7 @@ body {
37893789
as: 'style',
37903790
crossOrigin: 'use-credentials',
37913791
integrity: 'some hash',
3792+
fetchPriority: 'low',
37923793
});
37933794
return (
37943795
<html>
@@ -3909,6 +3910,113 @@ body {
39093910
'ReactDOM.preload(): For `href` "foo", The options provided conflict with props on a matching <link rel="stylesheet" ... /> element. When the preload options disagree with the underlying resource it usually means the browser will not be able to use the preload when the resource is fetched, negating any benefit the preload would provide. React will preload the resource using props derived from the resource instead and ignore the options provided to the `ReactDOM.preload()` call. In general, preloading is useful when you expect to render a resource soon but have not yet done so. In this case since the underlying resource was already rendered the preload call may be extraneous. Try removing the call, otherwise try adjusting both the props on the <link rel="stylesheet" ... /> and the options passed to `ReactDOM.preload()` to agree.\n "integrity" missing from options, underlying prop value: "some hash"\n "media" missing from options, underlying prop value: "print"\n "crossOrigin" option value: "use-credentials", missing from underlying props',
39103911
]);
39113912
});
3913+
3914+
it('supports fetchPriority', async () => {
3915+
function Component({isServer}) {
3916+
ReactDOM.preload(isServer ? 'highserver' : 'highclient', {
3917+
as: 'script',
3918+
fetchPriority: 'high',
3919+
});
3920+
ReactDOM.preload(isServer ? 'lowserver' : 'lowclient', {
3921+
as: 'style',
3922+
fetchPriority: 'low',
3923+
});
3924+
ReactDOM.preload(isServer ? 'autoserver' : 'autoclient', {
3925+
as: 'style',
3926+
fetchPriority: 'auto',
3927+
});
3928+
return 'hello';
3929+
}
3930+
3931+
await act(() => {
3932+
renderToPipeableStream(
3933+
<html>
3934+
<body>
3935+
<Component isServer={true} />
3936+
</body>
3937+
</html>,
3938+
).pipe(writable);
3939+
});
3940+
3941+
expect(getMeaningfulChildren(document)).toEqual(
3942+
<html>
3943+
<head>
3944+
<link
3945+
rel="preload"
3946+
as="style"
3947+
href="lowserver"
3948+
fetchpriority="low"
3949+
/>
3950+
<link
3951+
rel="preload"
3952+
as="style"
3953+
href="autoserver"
3954+
fetchpriority="auto"
3955+
/>
3956+
<link
3957+
rel="preload"
3958+
as="script"
3959+
href="highserver"
3960+
fetchpriority="high"
3961+
/>
3962+
</head>
3963+
<body>hello</body>
3964+
</html>,
3965+
);
3966+
3967+
ReactDOMClient.hydrateRoot(
3968+
document,
3969+
<html>
3970+
<body>
3971+
<Component />
3972+
</body>
3973+
</html>,
3974+
);
3975+
await waitForAll([]);
3976+
expect(getMeaningfulChildren(document)).toEqual(
3977+
<html>
3978+
<head>
3979+
<link
3980+
rel="preload"
3981+
as="style"
3982+
href="lowserver"
3983+
fetchpriority="low"
3984+
/>
3985+
<link
3986+
rel="preload"
3987+
as="style"
3988+
href="autoserver"
3989+
fetchpriority="auto"
3990+
/>
3991+
<link
3992+
rel="preload"
3993+
as="script"
3994+
href="highserver"
3995+
fetchpriority="high"
3996+
/>
3997+
<link
3998+
rel="preload"
3999+
as="script"
4000+
href="highclient"
4001+
fetchpriority="high"
4002+
/>
4003+
<link
4004+
rel="preload"
4005+
as="style"
4006+
href="lowclient"
4007+
fetchpriority="low"
4008+
/>
4009+
<link
4010+
rel="preload"
4011+
as="style"
4012+
href="autoclient"
4013+
fetchpriority="auto"
4014+
/>
4015+
</head>
4016+
<body>hello</body>
4017+
</html>,
4018+
);
4019+
});
39124020
});
39134021

39144022
describe('ReactDOM.preinit(href, { as: ... })', () => {
@@ -4442,7 +4550,6 @@ body {
44424550
<body>hello</body>
44434551
</html>,
44444552
);
4445-
44464553
await clientAct(() => {
44474554
ReactDOMClient.hydrateRoot(
44484555
document,
@@ -4453,7 +4560,6 @@ body {
44534560
</html>,
44544561
);
44554562
});
4456-
44574563
expect(getMeaningfulChildren(document)).toEqual(
44584564
<html>
44594565
<head>
@@ -4474,6 +4580,97 @@ body {
44744580
</html>,
44754581
);
44764582
});
4583+
4584+
it('supports fetchPriority', async () => {
4585+
function Component({isServer}) {
4586+
ReactDOM.preinit(isServer ? 'highserver' : 'highclient', {
4587+
as: 'script',
4588+
fetchPriority: 'high',
4589+
});
4590+
ReactDOM.preinit(isServer ? 'lowserver' : 'lowclient', {
4591+
as: 'style',
4592+
fetchPriority: 'low',
4593+
});
4594+
ReactDOM.preinit(isServer ? 'autoserver' : 'autoclient', {
4595+
as: 'style',
4596+
fetchPriority: 'auto',
4597+
});
4598+
return 'hello';
4599+
}
4600+
4601+
await act(() => {
4602+
renderToPipeableStream(
4603+
<html>
4604+
<body>
4605+
<Component isServer={true} />
4606+
</body>
4607+
</html>,
4608+
).pipe(writable);
4609+
});
4610+
4611+
expect(getMeaningfulChildren(document)).toEqual(
4612+
<html>
4613+
<head>
4614+
<link
4615+
rel="stylesheet"
4616+
href="lowserver"
4617+
fetchpriority="low"
4618+
data-precedence="default"
4619+
/>
4620+
<link
4621+
rel="stylesheet"
4622+
href="autoserver"
4623+
fetchpriority="auto"
4624+
data-precedence="default"
4625+
/>
4626+
<script async="" src="highserver" fetchpriority="high" />
4627+
</head>
4628+
<body>hello</body>
4629+
</html>,
4630+
);
4631+
ReactDOMClient.hydrateRoot(
4632+
document,
4633+
<html>
4634+
<body>
4635+
<Component />
4636+
</body>
4637+
</html>,
4638+
);
4639+
await waitForAll([]);
4640+
expect(getMeaningfulChildren(document)).toEqual(
4641+
<html>
4642+
<head>
4643+
<link
4644+
rel="stylesheet"
4645+
href="lowserver"
4646+
fetchpriority="low"
4647+
data-precedence="default"
4648+
/>
4649+
<link
4650+
rel="stylesheet"
4651+
href="autoserver"
4652+
fetchpriority="auto"
4653+
data-precedence="default"
4654+
/>
4655+
<link
4656+
rel="stylesheet"
4657+
href="lowclient"
4658+
fetchpriority="low"
4659+
data-precedence="default"
4660+
/>
4661+
<link
4662+
rel="stylesheet"
4663+
href="autoclient"
4664+
fetchpriority="auto"
4665+
data-precedence="default"
4666+
/>
4667+
<script async="" src="highserver" fetchpriority="high" />
4668+
<script async="" src="highclient" fetchpriority="high" />
4669+
</head>
4670+
<body>hello</body>
4671+
</html>,
4672+
);
4673+
});
44774674
});
44784675

44794676
describe('Stylesheet Resources', () => {

0 commit comments

Comments
 (0)