Skip to content

Commit 39c2c1d

Browse files
[Float] Support fetchPriority for module resources (react#36835)
1 parent 99e8606 commit 39c2c1d

4 files changed

Lines changed: 263 additions & 16 deletions

File tree

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

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6532,6 +6532,67 @@ body {
65326532
);
65336533
});
65346534

6535+
it('supports fetchPriority', async () => {
6536+
function Component({isServer}) {
6537+
const suffix = isServer ? 'server' : 'client';
6538+
ReactDOM.preloadModule('high' + suffix, {
6539+
fetchPriority: 'high',
6540+
});
6541+
ReactDOM.preloadModule('low' + suffix, {
6542+
fetchPriority: 'low',
6543+
});
6544+
ReactDOM.preloadModule('auto' + suffix, {
6545+
fetchPriority: 'auto',
6546+
});
6547+
return 'hello';
6548+
}
6549+
6550+
await act(() => {
6551+
renderToPipeableStream(
6552+
<html>
6553+
<body>
6554+
<Component isServer={true} />
6555+
</body>
6556+
</html>,
6557+
).pipe(writable);
6558+
});
6559+
6560+
expect(getMeaningfulChildren(document)).toEqual(
6561+
<html>
6562+
<head>
6563+
<link rel="modulepreload" href="highserver" fetchpriority="high" />
6564+
<link rel="modulepreload" href="lowserver" fetchpriority="low" />
6565+
<link rel="modulepreload" href="autoserver" fetchpriority="auto" />
6566+
</head>
6567+
<body>hello</body>
6568+
</html>,
6569+
);
6570+
6571+
ReactDOMClient.hydrateRoot(
6572+
document,
6573+
<html>
6574+
<body>
6575+
<Component />
6576+
</body>
6577+
</html>,
6578+
);
6579+
await waitForAll([]);
6580+
6581+
expect(getMeaningfulChildren(document)).toEqual(
6582+
<html>
6583+
<head>
6584+
<link rel="modulepreload" href="highserver" fetchpriority="high" />
6585+
<link rel="modulepreload" href="lowserver" fetchpriority="low" />
6586+
<link rel="modulepreload" href="autoserver" fetchpriority="auto" />
6587+
<link rel="modulepreload" href="highclient" fetchpriority="high" />
6588+
<link rel="modulepreload" href="lowclient" fetchpriority="low" />
6589+
<link rel="modulepreload" href="autoclient" fetchpriority="auto" />
6590+
</head>
6591+
<body>hello</body>
6592+
</html>,
6593+
);
6594+
});
6595+
65356596
it('preloads multiple non-script modules with the same as type', async () => {
65366597
function App() {
65376598
ReactDOM.preloadModule('serviceworker one', {as: 'serviceworker'});
@@ -7266,6 +7327,112 @@ body {
72667327
);
72677328
});
72687329

7330+
it('supports fetchPriority', async () => {
7331+
function Component({isServer}) {
7332+
const suffix = isServer ? 'server' : 'client';
7333+
ReactDOM.preinitModule('high' + suffix, {
7334+
fetchPriority: 'high',
7335+
});
7336+
ReactDOM.preinitModule('low' + suffix, {
7337+
fetchPriority: 'low',
7338+
});
7339+
ReactDOM.preinitModule('auto' + suffix, {
7340+
fetchPriority: 'auto',
7341+
});
7342+
return 'hello';
7343+
}
7344+
7345+
await act(() => {
7346+
renderToPipeableStream(
7347+
<html>
7348+
<body>
7349+
<Component isServer={true} />
7350+
</body>
7351+
</html>,
7352+
).pipe(writable);
7353+
});
7354+
7355+
expect(getMeaningfulChildren(document)).toEqual(
7356+
<html>
7357+
<head>
7358+
<script
7359+
type="module"
7360+
src="highserver"
7361+
fetchpriority="high"
7362+
async=""
7363+
/>
7364+
<script
7365+
type="module"
7366+
src="lowserver"
7367+
fetchpriority="low"
7368+
async=""
7369+
/>
7370+
<script
7371+
type="module"
7372+
src="autoserver"
7373+
fetchpriority="auto"
7374+
async=""
7375+
/>
7376+
</head>
7377+
<body>hello</body>
7378+
</html>,
7379+
);
7380+
7381+
ReactDOMClient.hydrateRoot(
7382+
document,
7383+
<html>
7384+
<body>
7385+
<Component />
7386+
</body>
7387+
</html>,
7388+
);
7389+
await waitForAll([]);
7390+
7391+
expect(getMeaningfulChildren(document)).toEqual(
7392+
<html>
7393+
<head>
7394+
<script
7395+
type="module"
7396+
src="highserver"
7397+
fetchpriority="high"
7398+
async=""
7399+
/>
7400+
<script
7401+
type="module"
7402+
src="lowserver"
7403+
fetchpriority="low"
7404+
async=""
7405+
/>
7406+
<script
7407+
type="module"
7408+
src="autoserver"
7409+
fetchpriority="auto"
7410+
async=""
7411+
/>
7412+
<script
7413+
type="module"
7414+
src="highclient"
7415+
fetchpriority="high"
7416+
async=""
7417+
/>
7418+
<script
7419+
type="module"
7420+
src="lowclient"
7421+
fetchpriority="low"
7422+
async=""
7423+
/>
7424+
<script
7425+
type="module"
7426+
src="autoclient"
7427+
fetchpriority="auto"
7428+
async=""
7429+
/>
7430+
</head>
7431+
<body>hello</body>
7432+
</html>,
7433+
);
7434+
});
7435+
72697436
it('warns if you provide invalid arguments', async () => {
72707437
function App() {
72717438
ReactDOM.preinitModule();

packages/react-dom/src/shared/ReactDOMFloat.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ export function preloadModule(href: string, options?: ?PreloadModuleOptions) {
192192
typeof options.integrity === 'string'
193193
? options.integrity
194194
: undefined,
195+
fetchPriority:
196+
typeof options.fetchPriority === 'string'
197+
? options.fetchPriority
198+
: undefined,
195199
});
196200
} else {
197201
ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */
@@ -321,6 +325,10 @@ export function preinitModule(href: string, options?: ?PreinitModuleOptions) {
321325
: undefined,
322326
nonce:
323327
typeof options.nonce === 'string' ? options.nonce : undefined,
328+
fetchPriority:
329+
typeof options.fetchPriority === 'string'
330+
? options.fetchPriority
331+
: undefined,
324332
});
325333
}
326334
} else if (options == null) {

packages/react-dom/src/shared/ReactDOMTypes.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type PreloadModuleOptions = {
2828
crossOrigin?: string,
2929
integrity?: string,
3030
nonce?: string,
31+
fetchPriority?: FetchPriorityEnum,
3132
};
3233
export type PreinitOptions = {
3334
as: string,
@@ -42,6 +43,7 @@ export type PreinitModuleOptions = {
4243
crossOrigin?: string,
4344
integrity?: string,
4445
nonce?: string,
46+
fetchPriority?: FetchPriorityEnum,
4547
};
4648

4749
export type CrossOriginEnum = '' | 'use-credentials' | CrossOriginString;
@@ -63,6 +65,7 @@ export type PreloadModuleImplOptions = {
6365
crossOrigin?: ?CrossOriginEnum,
6466
integrity?: ?string,
6567
nonce?: ?string,
68+
fetchPriority?: ?string,
6669
};
6770
export type PreinitStyleOptions = {
6871
crossOrigin?: ?CrossOriginEnum,
@@ -79,6 +82,7 @@ export type PreinitModuleScriptOptions = {
7982
crossOrigin?: ?CrossOriginEnum,
8083
integrity?: ?string,
8184
nonce?: ?string,
85+
fetchPriority?: ?string,
8286
};
8387

8488
export type HostDispatcher = {

packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,20 +1704,32 @@ describe('ReactFlightDOM', () => {
17041704
FlightReactDOM.preconnect('c2 before', {crossOrigin: 'anonymous'});
17051705
FlightReactDOM.preload('l before', {as: 'style'});
17061706
FlightReactDOM.preloadModule('lm before');
1707-
FlightReactDOM.preloadModule('lm2 before', {crossOrigin: 'anonymous'});
1707+
FlightReactDOM.preloadModule('lm2 before', {
1708+
crossOrigin: 'anonymous',
1709+
fetchPriority: 'low',
1710+
});
17081711
FlightReactDOM.preinit('i before', {as: 'script'});
17091712
FlightReactDOM.preinitModule('m before');
1710-
FlightReactDOM.preinitModule('m2 before', {crossOrigin: 'anonymous'});
1713+
FlightReactDOM.preinitModule('m2 before', {
1714+
crossOrigin: 'anonymous',
1715+
fetchPriority: 'high',
1716+
});
17111717
await 1;
17121718
FlightReactDOM.prefetchDNS('d after');
17131719
FlightReactDOM.preconnect('c after');
17141720
FlightReactDOM.preconnect('c2 after', {crossOrigin: 'anonymous'});
17151721
FlightReactDOM.preload('l after', {as: 'style'});
17161722
FlightReactDOM.preloadModule('lm after');
1717-
FlightReactDOM.preloadModule('lm2 after', {crossOrigin: 'anonymous'});
1723+
FlightReactDOM.preloadModule('lm2 after', {
1724+
crossOrigin: 'anonymous',
1725+
fetchPriority: 'low',
1726+
});
17181727
FlightReactDOM.preinit('i after', {as: 'script'});
17191728
FlightReactDOM.preinitModule('m after');
1720-
FlightReactDOM.preinitModule('m2 after', {crossOrigin: 'anonymous'});
1729+
FlightReactDOM.preinitModule('m2 after', {
1730+
crossOrigin: 'anonymous',
1731+
fetchPriority: 'high',
1732+
});
17211733
return <ClientComponent />;
17221734
}
17231735

@@ -1766,19 +1778,41 @@ describe('ReactFlightDOM', () => {
17661778
<link rel="preconnect" href="c2 before" crossorigin="" />
17671779
<link rel="preload" as="style" href="l before" />
17681780
<link rel="modulepreload" href="lm before" />
1769-
<link rel="modulepreload" href="lm2 before" crossorigin="" />
1781+
<link
1782+
rel="modulepreload"
1783+
href="lm2 before"
1784+
crossorigin=""
1785+
fetchpriority="low"
1786+
/>
17701787
<script async="" src="i before" />
17711788
<script type="module" async="" src="m before" />
1772-
<script type="module" async="" src="m2 before" crossorigin="" />
1789+
<script
1790+
type="module"
1791+
async=""
1792+
src="m2 before"
1793+
crossorigin=""
1794+
fetchpriority="high"
1795+
/>
17731796
<link rel="dns-prefetch" href="d after" />
17741797
<link rel="preconnect" href="c after" />
17751798
<link rel="preconnect" href="c2 after" crossorigin="" />
17761799
<link rel="preload" as="style" href="l after" />
17771800
<link rel="modulepreload" href="lm after" />
1778-
<link rel="modulepreload" href="lm2 after" crossorigin="" />
1801+
<link
1802+
rel="modulepreload"
1803+
href="lm2 after"
1804+
crossorigin=""
1805+
fetchpriority="low"
1806+
/>
17791807
<script async="" src="i after" />
17801808
<script type="module" async="" src="m after" />
1781-
<script type="module" async="" src="m2 after" crossorigin="" />
1809+
<script
1810+
type="module"
1811+
async=""
1812+
src="m2 after"
1813+
crossorigin=""
1814+
fetchpriority="high"
1815+
/>
17821816
</head>
17831817
<body />
17841818
</html>,
@@ -1799,20 +1833,32 @@ describe('ReactFlightDOM', () => {
17991833
FlightReactDOM.preconnect('c2 before', {crossOrigin: 'anonymous'});
18001834
FlightReactDOM.preload('l before', {as: 'style'});
18011835
FlightReactDOM.preloadModule('lm before');
1802-
FlightReactDOM.preloadModule('lm2 before', {crossOrigin: 'anonymous'});
1836+
FlightReactDOM.preloadModule('lm2 before', {
1837+
crossOrigin: 'anonymous',
1838+
fetchPriority: 'low',
1839+
});
18031840
FlightReactDOM.preinit('i before', {as: 'script'});
18041841
FlightReactDOM.preinitModule('m before');
1805-
FlightReactDOM.preinitModule('m2 before', {crossOrigin: 'anonymous'});
1842+
FlightReactDOM.preinitModule('m2 before', {
1843+
crossOrigin: 'anonymous',
1844+
fetchPriority: 'high',
1845+
});
18061846
await 1;
18071847
FlightReactDOM.prefetchDNS('d after');
18081848
FlightReactDOM.preconnect('c after');
18091849
FlightReactDOM.preconnect('c2 after', {crossOrigin: 'anonymous'});
18101850
FlightReactDOM.preload('l after', {as: 'style'});
18111851
FlightReactDOM.preloadModule('lm after');
1812-
FlightReactDOM.preloadModule('lm2 after', {crossOrigin: 'anonymous'});
1852+
FlightReactDOM.preloadModule('lm2 after', {
1853+
crossOrigin: 'anonymous',
1854+
fetchPriority: 'low',
1855+
});
18131856
FlightReactDOM.preinit('i after', {as: 'script'});
18141857
FlightReactDOM.preinitModule('m after');
1815-
FlightReactDOM.preinitModule('m2 after', {crossOrigin: 'anonymous'});
1858+
FlightReactDOM.preinitModule('m2 after', {
1859+
crossOrigin: 'anonymous',
1860+
fetchPriority: 'high',
1861+
});
18161862
return <ClientComponent />;
18171863
}
18181864

@@ -1866,16 +1912,38 @@ describe('ReactFlightDOM', () => {
18661912
<link rel="preconnect" href="c2 after" crossorigin="" />
18671913
<script async="" src="i before" />
18681914
<script type="module" async="" src="m before" />
1869-
<script type="module" async="" src="m2 before" crossorigin="" />
1915+
<script
1916+
type="module"
1917+
async=""
1918+
src="m2 before"
1919+
crossorigin=""
1920+
fetchpriority="high"
1921+
/>
18701922
<script async="" src="i after" />
18711923
<script type="module" async="" src="m after" />
1872-
<script type="module" async="" src="m2 after" crossorigin="" />
1924+
<script
1925+
type="module"
1926+
async=""
1927+
src="m2 after"
1928+
crossorigin=""
1929+
fetchpriority="high"
1930+
/>
18731931
<link rel="preload" as="style" href="l before" />
18741932
<link rel="modulepreload" href="lm before" />
1875-
<link rel="modulepreload" href="lm2 before" crossorigin="" />
1933+
<link
1934+
rel="modulepreload"
1935+
href="lm2 before"
1936+
crossorigin=""
1937+
fetchpriority="low"
1938+
/>
18761939
<link rel="preload" as="style" href="l after" />
18771940
<link rel="modulepreload" href="lm after" />
1878-
<link rel="modulepreload" href="lm2 after" crossorigin="" />
1941+
<link
1942+
rel="modulepreload"
1943+
href="lm2 after"
1944+
crossorigin=""
1945+
fetchpriority="low"
1946+
/>
18791947
</head>
18801948
<body>
18811949
<p>hello world</p>

0 commit comments

Comments
 (0)