From 1a001dac6220a64d98ae33a28e89dde78100d6c5 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Sat, 12 Aug 2023 09:21:45 -0700 Subject: [PATCH] [Fizz][Float] When src or srcSet is a data URI we should not preload the image (#27218) Data URI's in images can't effectively be preloaded (the URI contains the data so preloading only duplicates the data in the stream. If we encounter an image with this protocol in the src attribute we should avoid preloading it. --- .../src/server/ReactFizzConfigDOM.js | 24 +++++++++++++-- .../src/__tests__/ReactDOMFloat-test.js | 30 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index 72c5c08d8e40c..cccc3d0a76562 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -2392,14 +2392,32 @@ function pushImg( props: Object, resources: Resources, ): null { + const {src, srcSet} = props; if ( props.loading !== 'lazy' && - typeof props.src === 'string' && - props.fetchPriority !== 'low' + (typeof src === 'string' || typeof srcSet === 'string') && + props.fetchPriority !== 'low' && + // We exclude data URIs in src and srcSet since these should not be preloaded + !( + typeof src === 'string' && + src[4] === ':' && + (src[0] === 'd' || src[0] === 'D') && + (src[1] === 'a' || src[1] === 'A') && + (src[2] === 't' || src[2] === 'T') && + (src[3] === 'a' || src[3] === 'A') + ) && + !( + typeof srcSet === 'string' && + srcSet[4] === ':' && + (srcSet[0] === 'd' || srcSet[0] === 'D') && + (srcSet[1] === 'a' || srcSet[1] === 'A') && + (srcSet[2] === 't' || srcSet[2] === 'T') && + (srcSet[3] === 'a' || srcSet[3] === 'A') + ) ) { // We have a suspensey image and ought to preload it to optimize the loading of display blocking // resources. - const {src, srcSet, sizes} = props; + const {sizes} = props; const key = getImagePreloadKey(src, srcSet, sizes); let resource = resources.preloadsMap.get(key); if (!resource) { diff --git a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js index e8a4f621ee95c..53aa2e75f77ca 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js @@ -3969,6 +3969,36 @@ body { ); }); + it('should not preload images that have a data URIs for src or srcSet', async () => { + function App() { + return ( + + + + + + + + + ); + } + await act(() => { + renderToPipeableStream().pipe(writable); + }); + + expect(getMeaningfulChildren(document)).toEqual( + + + + + + + + + , + ); + }); + describe('ReactDOM.prefetchDNS(href)', () => { it('creates a dns-prefetch resource when called', async () => { function App({url}) {