Skip to content

Commit

Permalink
[Float][Fizz]: Don't preload nomodule scripts (#26353)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gnoff authored Mar 9, 2023
1 parent 2b003a5 commit 3706edb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2056,25 +2056,28 @@ function pushScript(
const src = props.src;
const key = getResourceKey('script', src);
if (props.async !== true || props.onLoad || props.onError) {
// We can't resourcify scripts with load listeners. To avoid ambiguity with
// other Resourcified async scripts on the server we omit them from the server
// stream and expect them to be inserted during hydration on the client.
// We can still preload them however so the client can start fetching the script
// as soon as possible
let resource = resources.preloadsMap.get(key);
if (!resource) {
resource = {
type: 'preload',
chunks: [],
state: NoState,
props: preloadAsScriptPropsFromProps(props.src, props),
};
resources.preloadsMap.set(key, resource);
if (__DEV__) {
markAsImplicitResourceDEV(resource, props, resource.props);
// we don't want to preload nomodule scripts
if (props.noModule !== true) {
// We can't resourcify scripts with load listeners. To avoid ambiguity with
// other Resourcified async scripts on the server we omit them from the server
// stream and expect them to be inserted during hydration on the client.
// We can still preload them however so the client can start fetching the script
// as soon as possible
let resource = resources.preloadsMap.get(key);
if (!resource) {
resource = {
type: 'preload',
chunks: [],
state: NoState,
props: preloadAsScriptPropsFromProps(props.src, props),
};
resources.preloadsMap.set(key, resource);
if (__DEV__) {
markAsImplicitResourceDEV(resource, props, resource.props);
}
resources.usedScripts.add(resource);
pushLinkImpl(resource.chunks, resource.props);
}
resources.usedScripts.add(resource);
pushLinkImpl(resource.chunks, resource.props);
}

if (props.async !== true) {
Expand Down
23 changes: 23 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMFloat-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2639,6 +2639,29 @@ body {
);
});

it('does not preload nomodule scripts', async () => {
await actIntoEmptyDocument(() => {
renderToPipeableStream(
<html>
<body>
<script src="foo" noModule={true} data-meaningful="" />
<script async={true} src="bar" noModule={true} data-meaningful="" />
</body>
</html>,
).pipe(writable);
});
expect(getMeaningfulChildren(document)).toEqual(
<html>
<head>
<script async="" src="bar" nomodule="" data-meaningful="" />
</head>
<body>
<script src="foo" nomodule="" data-meaningful="" />
</body>
</html>,
);
});

describe('ReactDOM.prefetchDNS(href)', () => {
it('creates a dns-prefetch resource when called', async () => {
function App({url}) {
Expand Down

0 comments on commit 3706edb

Please sign in to comment.