[Float] Don't preload images inside `<noscript>` (#28815)
`<noscript>` scopes should be considered inert from the perspective of Fizz since we assume they'll only be used in rare and adverse circumstances. When we added preload support for img tags we did not include the noscript scope check in the opt-out for preloading. This change adds it in fixes: #27910
Josh Story committed
Apr 10, 2024 at 12:15 UTC
dc6a7e01e1d2fa5eb4974f9bb66e9e8fb40f6ef8
2 files changed
+35
-3
packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
+3
-3
@@ -2762,7 +2762,7 @@ function pushImg(
2762
props: Object,
2763
resumableState: ResumableState,
2764
renderState: RenderState,
2765
- pictureTagInScope: boolean,
2765
+ pictureOrNoScriptTagInScope: boolean,
2766
): null {
2767
const {src, srcSet} = props;
2768
if (
@@ -2771,7 +2771,7 @@ function pushImg(
2771
(typeof src === 'string' || src == null) &&
2772
(typeof srcSet === 'string' || srcSet == null) &&
2773
props.fetchPriority !== 'low' &&
2774
- pictureTagInScope === false &&
2774
+ pictureOrNoScriptTagInScope === false &&
2775
// We exclude data URIs in src and srcSet since these should not be preloaded
2776
!(
2777
typeof src === 'string' &&
@@ -3599,7 +3599,7 @@ export function pushStartInstance(
3599
props,
3600
resumableState,
3601
renderState,
3602
- !!(formatContext.tagScope & PICTURE_SCOPE),
3602
+ !!(formatContext.tagScope & (PICTURE_SCOPE | NOSCRIPT_SCOPE)),
3603
);
3604
}
3605
// Omitted close tags
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+32
@@ -4261,6 +4261,38 @@ body {
4261
);
4262
});
4263
4264
+ // Fixes: https://github.com/facebook/react/issues/27910
4265
+ it('omits preloads for images inside noscript tags', async () => {
4266
+ function App() {
4267
+ return (
4268
+ <html>
4269
+ <body>
4270
+ <img src="foo" />
4271
+ <noscript>
4272
+ <img src="bar" />
4273
+ </noscript>
4274
+ </body>
4275
+ </html>
4276
+ );
4277
+ }
4278
+
4279
+ await act(() => {
4280
+ renderToPipeableStream(<App />).pipe(writable);
4281
+ });
4282
+
4283
+ expect(getMeaningfulChildren(document)).toEqual(
4284
+ <html>
4285
+ <head>
4286
+ <link rel="preload" href="foo" as="image" />
4287
+ </head>
4288
+ <body>
4289
+ <img src="foo" />
4290
+ <noscript><img src="bar"></noscript>
4291
+ </body>
4292
+ </html>,
4293
+ );
4294
+ });
4295
+
4296
it('should handle media on image preload', async () => {
4297
function App({isClient}) {
4298
ReactDOM.preload('/server', {