Skip to content

Commit 9b042f9

Browse files
authored
[Fizz] Responsive images should not be preloaded with link headers (#32445)
Link headers are optionally supported for cases where you prefer to send resource loading hints before you're ready to send the body of a request. While many resources can be correctly preloaded from a link header responsive images are currently not supported and end up preloading the default src rather than the correctly sized image. Until responsive images are supported React will not allow these images to preload as headers and will retain them to preload as HTML. closes: #32437
1 parent 27ba5e8 commit 9b042f9

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

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

+7
Original file line numberDiff line numberDiff line change
@@ -2958,6 +2958,9 @@ function pushImg(
29582958
if (
29592959
headers &&
29602960
headers.remainingCapacity > 0 &&
2961+
// browsers today don't support preloading responsive images from link headers so we bail out
2962+
// if the img has srcset defined
2963+
typeof props.srcSet !== 'string' &&
29612964
// this is a hueristic similar to capping element preloads to 10 unless explicitly
29622965
// fetchPriority="high". We use length here which means it will fit fewer images when
29632966
// the urls are long and more when short. arguably byte size is a better hueristic because
@@ -5703,6 +5706,10 @@ function preload(href: string, as: string, options?: ?PreloadImplOptions) {
57035706
if (
57045707
headers &&
57055708
headers.remainingCapacity > 0 &&
5709+
// browsers today don't support preloading responsive images from link headers so we bail out
5710+
// if the img has srcset defined
5711+
typeof imageSrcSet !== 'string' &&
5712+
// We only include high priority images in the link header
57065713
fetchPriority === 'high' &&
57075714
// Compute the header since we might be able to fit it in the max length
57085715
((header = getPreloadAsHeader(href, as, options)),

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

+27-7
Original file line numberDiff line numberDiff line change
@@ -3723,23 +3723,43 @@ describe('ReactDOMFizzServer', () => {
37233723
});
37243724
});
37253725

3726-
it('encodes img srcset and sizes into preload header params', async () => {
3726+
it('omits images from preload headers if they contain srcset and sizes', async () => {
37273727
let headers = null;
37283728
function onHeaders(x) {
37293729
headers = x;
37303730
}
37313731

37323732
function App() {
3733-
ReactDOM.preload('presrc', {
3733+
ReactDOM.preload('responsive-preload-set-only', {
3734+
as: 'image',
3735+
fetchPriority: 'high',
3736+
imageSrcSet: 'srcset',
3737+
});
3738+
ReactDOM.preload('responsive-preload', {
3739+
as: 'image',
3740+
fetchPriority: 'high',
3741+
imageSrcSet: 'srcset',
3742+
imageSizes: 'sizes',
3743+
});
3744+
ReactDOM.preload('non-responsive-preload', {
37343745
as: 'image',
37353746
fetchPriority: 'high',
3736-
imageSrcSet: 'presrcset',
3737-
imageSizes: 'presizes',
37383747
});
37393748
return (
37403749
<html>
37413750
<body>
3742-
<img src="src" srcSet="srcset" sizes="sizes" />
3751+
<img
3752+
src="responsive-img-set-only"
3753+
fetchPriority="high"
3754+
srcSet="srcset"
3755+
/>
3756+
<img
3757+
src="responsive-img"
3758+
fetchPriority="high"
3759+
srcSet="srcset"
3760+
sizes="sizes"
3761+
/>
3762+
<img src="non-responsive-img" fetchPriority="high" />
37433763
</body>
37443764
</html>
37453765
);
@@ -3751,8 +3771,8 @@ describe('ReactDOMFizzServer', () => {
37513771

37523772
expect(headers).toEqual({
37533773
Link: `
3754-
<presrc>; rel=preload; as="image"; fetchpriority="high"; imagesrcset="presrcset"; imagesizes="presizes",
3755-
<src>; rel=preload; as="image"; imagesrcset="srcset"; imagesizes="sizes"
3774+
<non-responsive-preload>; rel=preload; as="image"; fetchpriority="high",
3775+
<non-responsive-img>; rel=preload; as="image"; fetchpriority="high"
37563776
`
37573777
.replaceAll('\n', '')
37583778
.trim(),

0 commit comments

Comments
 (0)