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 bcb9e96 commit e5c2ed4
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 @@ -2161,6 +2161,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 @@ -2233,6 +2234,7 @@ function preloadPropsFromPreloadOptions(
crossOrigin: as === 'font' ? '' : options.crossOrigin,
integrity: options.integrity,
type: options.type,
fetchPriority: options.fetchPriority,
};
}
Expand All @@ -2242,6 +2244,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 @@ -2383,6 +2386,7 @@ function stylesheetPropsFromPreinitOptions(
'data-precedence': precedence,
crossOrigin: options.crossOrigin,
integrity: options.integrity,
fetchPriority: options.fetchPriority,
};
}
Expand All @@ -2396,6 +2400,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 @@ -5010,6 +5010,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 @@ -5155,6 +5156,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 @@ -5418,6 +5420,7 @@ function preloadPropsFromPreloadOptions(
crossOrigin: as === 'font' ? '' : options.crossOrigin,
integrity: options.integrity,
type: options.type,
fetchPriority: options.fetchPriority,
};
}

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

Expand Down Expand Up @@ -5477,6 +5481,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 @@ -3873,6 +3873,113 @@ body {
'Warning: ReactDOM.preload(): The options provided conflict with another call to `ReactDOM.preload("foo", { as: "font", ...})`. React will always use the options it first encounters when preloading a resource for a given `href` and `as` type, and any later options will be ignored if different. Try updating all calls to `ReactDOM.preload()` with the same `href` and `as` type to use the same options, or eliminate one of the calls.\n "crossOrigin" missing from options, original option value: "use-credentials"',
]);
});

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 @@ -4406,7 +4513,6 @@ body {
<body>hello</body>
</html>,
);

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

expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
Expand All @@ -4438,6 +4543,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 e5c2ed4

Please sign in to comment.