Skip to content

Commit

Permalink
support fetchPriority as an option for ReactDOM.preload() and ReactDO…
Browse files Browse the repository at this point in the history
…M.preinit()
  • Loading branch information
gnoff committed May 31, 2023
1 parent e1e68b9 commit 0cbcc01
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 2 deletions.
5 changes: 5 additions & 0 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,7 @@ type PreloadOptions = {
crossOrigin?: string,
integrity?: string,
type?: string,
fetchPriority?: 'high' | 'low' | 'auto',
};
function preload(href: string, options: PreloadOptions) {
if (!enableFloat) {
Expand Down Expand Up @@ -2245,6 +2246,7 @@ function preloadPropsFromPreloadOptions(
crossOrigin: as === 'font' ? '' : options.crossOrigin,
integrity: options.integrity,
type: options.type,
fetchPriority: options.fetchPriority,
};
}

Expand All @@ -2254,6 +2256,7 @@ type PreinitOptions = {
crossOrigin?: string,
integrity?: string,
nonce?: string,
fetchPriority?: 'high' | 'low' | 'auto',
};
function preinit(href: string, options: PreinitOptions) {
if (!enableFloat) {
Expand Down Expand Up @@ -2395,6 +2398,7 @@ function stylesheetPropsFromPreinitOptions(
'data-precedence': precedence,
crossOrigin: options.crossOrigin,
integrity: options.integrity,
fetchPriority: options.fetchPriority,
};
}

Expand All @@ -2408,6 +2412,7 @@ function scriptPropsFromPreinitOptions(
crossOrigin: options.crossOrigin,
integrity: options.integrity,
nonce: options.nonce,
fetchPriority: options.fetchPriority,
};
}

Expand Down
5 changes: 5 additions & 0 deletions packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -5093,6 +5093,7 @@ type PreloadOptions = {
crossOrigin?: string,
integrity?: string,
type?: string,
fetchPriority?: 'high' | 'low' | 'auto',
};
export function preload(href: string, options: PreloadOptions) {
if (!enableFloat) {
Expand Down Expand Up @@ -5238,6 +5239,7 @@ type PreinitOptions = {
crossOrigin?: string,
integrity?: string,
nonce?: string,
fetchPriority?: 'high' | 'low' | 'auto',
};
function preinit(href: string, options: PreinitOptions): void {
if (!enableFloat) {
Expand Down Expand Up @@ -5501,6 +5503,7 @@ function preloadPropsFromPreloadOptions(
crossOrigin: as === 'font' ? '' : options.crossOrigin,
integrity: options.integrity,
type: options.type,
fetchPriority: options.fetchPriority,
};
}

Expand Down Expand Up @@ -5542,6 +5545,7 @@ function stylesheetPropsFromPreinitOptions(
'data-precedence': precedence,
crossOrigin: options.crossOrigin,
integrity: options.integrity,
fetchPriority: options.fetchPriority,
};
}

Expand Down Expand Up @@ -5573,6 +5577,7 @@ function scriptPropsFromPreinitOptions(
crossOrigin: options.crossOrigin,
integrity: options.integrity,
nonce: options.nonce,
fetchPriority: options.fetchPriority,
};
}

Expand Down
2 changes: 2 additions & 0 deletions packages/react-dom/src/ReactDOMDispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ export type PreloadOptions = {
crossOrigin?: string,
integrity?: string,
type?: string,
fetchPriority?: 'high' | 'low' | 'auto',
};
export type PreinitOptions = {
as: string,
precedence?: string,
crossOrigin?: string,
integrity?: string,
nonce?: string,
fetchPriority?: 'high' | 'low' | 'auto',
};

export type HostDispatcher = {
Expand Down
200 changes: 198 additions & 2 deletions packages/react-dom/src/__tests__/ReactDOMFloat-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3909,6 +3909,113 @@ body {
'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',
]);
});

it('supports fetchPriority', async () => {
function Component({isServer}) {
ReactDOM.preload(isServer ? 'highserver' : 'highclient', {
as: 'script',
fetchPriority: 'high',
});
ReactDOM.preload(isServer ? 'lowserver' : 'lowclient', {
as: 'style',
fetchPriority: 'low',
});
ReactDOM.preload(isServer ? 'autoserver' : 'autoclient', {
as: 'style',
fetchPriority: 'auto',
});
return 'hello';
}

await act(() => {
renderToPipeableStream(
<html>
<body>
<Component isServer={true} />
</body>
</html>,
).pipe(writable);
});

expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
<link
rel="preload"
as="style"
href="lowserver"
fetchpriority="low"
/>
<link
rel="preload"
as="style"
href="autoserver"
fetchpriority="auto"
/>
<link
rel="preload"
as="script"
href="highserver"
fetchpriority="high"
/>
</head>
<body>hello</body>
</html>,
);

ReactDOMClient.hydrateRoot(
document,
<html>
<body>
<Component />
</body>
</html>,
);
await waitForAll([]);
expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
<link
rel="preload"
as="style"
href="lowserver"
fetchpriority="low"
/>
<link
rel="preload"
as="style"
href="autoserver"
fetchpriority="auto"
/>
<link
rel="preload"
as="script"
href="highserver"
fetchpriority="high"
/>
<link
rel="preload"
as="script"
href="highclient"
fetchpriority="high"
/>
<link
rel="preload"
as="style"
href="lowclient"
fetchpriority="low"
/>
<link
rel="preload"
as="style"
href="autoclient"
fetchpriority="auto"
/>
</head>
<body>hello</body>
</html>,
);
});
});

describe('ReactDOM.preinit(href, { as: ... })', () => {
Expand Down Expand Up @@ -4442,7 +4549,6 @@ body {
<body>hello</body>
</html>,
);

await clientAct(() => {
ReactDOMClient.hydrateRoot(
document,
Expand All @@ -4453,7 +4559,6 @@ body {
</html>,
);
});

expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
Expand All @@ -4474,6 +4579,97 @@ body {
</html>,
);
});

it('supports fetchPriority', async () => {
function Component({isServer}) {
ReactDOM.preinit(isServer ? 'highserver' : 'highclient', {
as: 'script',
fetchPriority: 'high',
});
ReactDOM.preinit(isServer ? 'lowserver' : 'lowclient', {
as: 'style',
fetchPriority: 'low',
});
ReactDOM.preinit(isServer ? 'autoserver' : 'autoclient', {
as: 'style',
fetchPriority: 'auto',
});
return 'hello';
}

await act(() => {
renderToPipeableStream(
<html>
<body>
<Component isServer={true} />
</body>
</html>,
).pipe(writable);
});

expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
<link
rel="stylesheet"
href="lowserver"
fetchpriority="low"
data-precedence="default"
/>
<link
rel="stylesheet"
href="autoserver"
fetchpriority="auto"
data-precedence="default"
/>
<script async="" src="highserver" fetchpriority="high" />
</head>
<body>hello</body>
</html>,
);
ReactDOMClient.hydrateRoot(
document,
<html>
<body>
<Component />
</body>
</html>,
);
await waitForAll([]);
expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
<link
rel="stylesheet"
href="lowserver"
fetchpriority="low"
data-precedence="default"
/>
<link
rel="stylesheet"
href="autoserver"
fetchpriority="auto"
data-precedence="default"
/>
<link
rel="stylesheet"
href="lowclient"
fetchpriority="low"
data-precedence="default"
/>
<link
rel="stylesheet"
href="autoclient"
fetchpriority="auto"
data-precedence="default"
/>
<script async="" src="highserver" fetchpriority="high" />
<script async="" src="highclient" fetchpriority="high" />
</head>
<body>hello</body>
</html>,
);
});
});

describe('Stylesheet Resources', () => {
Expand Down

0 comments on commit 0cbcc01

Please sign in to comment.