@samitouri / QOS-React-2 / commits / 3706edb81c

[Float][Fizz]: Don't preload nomodule scripts (#26353)

We attempt to preload scripts that we detect during Fizz rendering however when `noModule={true}` we should not because it will force modern browser to fetch scripts they will never execute Hoisted script resources already don't preload because we just emit the resource immediately. This change currently on affects the preloads for scripts that aren't hoistable

Josh Story committed Mar 8, 2023 at 21:59 UTC 3706edb81c84ea01e68bfb477537ba9908e1bd70
2 files changed +44 -18
packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js
+21 -18
@@ -2056,25 +2056,28 @@ function pushScript(
2056 const src = props.src;
2057 const key = getResourceKey('script', src);
2058 if (props.async !== true || props.onLoad || props.onError) {
2059 - // We can't resourcify scripts with load listeners. To avoid ambiguity with
2060 - // other Resourcified async scripts on the server we omit them from the server
2061 - // stream and expect them to be inserted during hydration on the client.
2062 - // We can still preload them however so the client can start fetching the script
2063 - // as soon as possible
2064 - let resource = resources.preloadsMap.get(key);
2065 - if (!resource) {
2066 - resource = {
2067 - type: 'preload',
2068 - chunks: [],
2069 - state: NoState,
2070 - props: preloadAsScriptPropsFromProps(props.src, props),
2071 - };
2072 - resources.preloadsMap.set(key, resource);
2073 - if (__DEV__) {
2074 - markAsImplicitResourceDEV(resource, props, resource.props);
2059 + // we don't want to preload nomodule scripts
2060 + if (props.noModule !== true) {
2061 + // We can't resourcify scripts with load listeners. To avoid ambiguity with
2062 + // other Resourcified async scripts on the server we omit them from the server
2063 + // stream and expect them to be inserted during hydration on the client.
2064 + // We can still preload them however so the client can start fetching the script
2065 + // as soon as possible
2066 + let resource = resources.preloadsMap.get(key);
2067 + if (!resource) {
2068 + resource = {
2069 + type: 'preload',
2070 + chunks: [],
2071 + state: NoState,
2072 + props: preloadAsScriptPropsFromProps(props.src, props),
2073 + };
2074 + resources.preloadsMap.set(key, resource);
2075 + if (__DEV__) {
2076 + markAsImplicitResourceDEV(resource, props, resource.props);
2077 + }
2078 + resources.usedScripts.add(resource);
2079 + pushLinkImpl(resource.chunks, resource.props);
2080 }
2076 - resources.usedScripts.add(resource);
2077 - pushLinkImpl(resource.chunks, resource.props);
2081 }
2082
2083 if (props.async !== true) {
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+23
@@ -2639,6 +2639,29 @@ body {
2639 );
2640 });
2641
2642 + it('does not preload nomodule scripts', async () => {
2643 + await actIntoEmptyDocument(() => {
2644 + renderToPipeableStream(
2645 + <html>
2646 + <body>
2647 + <script src="foo" noModule={true} data-meaningful="" />
2648 + <script async={true} src="bar" noModule={true} data-meaningful="" />
2649 + </body>
2650 + </html>,
2651 + ).pipe(writable);
2652 + });
2653 + expect(getMeaningfulChildren(document)).toEqual(
2654 + <html>
2655 + <head>
2656 + <script async="" src="bar" nomodule="" data-meaningful="" />
2657 + </head>
2658 + <body>
2659 + <script src="foo" nomodule="" data-meaningful="" />
2660 + </body>
2661 + </html>,
2662 + );
2663 + });
2664 +
2665 describe('ReactDOM.prefetchDNS(href)', () => {
2666 it('creates a dns-prefetch resource when called', async () => {
2667 function App({url}) {