From 7f8cee857193b91d4a8e13692d5d925f3a1e3783 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}) {