Skip to content

Commit e490dbe

Browse files
committed
Avoid bundling react-dom/server.browser in Pages router
This was a regression introduced when extending support for Pages router to React 18. We have to keep the `try-catch` when the pages runtime is used as an external (e.g. when the Node.js runtime is used). However, when bundling, we can alias the module relevant to choosing the correct `react-dom/server` entrypoint to the one we actually want.
1 parent 565abf2 commit e490dbe

File tree

7 files changed

+23
-35
lines changed

7 files changed

+23
-35
lines changed

crates/next-core/src/next_import_map.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,15 @@ async fn insert_next_server_special_aliases(
567567
external_esm_if_node(project_path, "next/dist/compiled/@vercel/og/index.node.js"),
568568
);
569569

570+
import_map.insert_exact_alias(
571+
"next/dist/server/ReactDOMServerPages",
572+
ImportMapping::Alternatives(vec![
573+
request_to_import_mapping(project_path, "react-dom/server.edge"),
574+
request_to_import_mapping(project_path, "react-dom/server.browser"),
575+
])
576+
.cell(),
577+
);
578+
570579
import_map.insert_exact_alias(
571580
"@opentelemetry/api",
572581
// It needs to prefer the local version of @opentelemetry/api

packages/next/src/build/create-compiler-aliases.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'path'
2+
import * as React from 'react'
23
import {
34
DOT_NEXT_ALIAS,
45
PAGES_DIR_ALIAS,
@@ -21,6 +22,8 @@ interface CompilerAliases {
2122
[alias: string]: string | string[]
2223
}
2324

25+
const isReact19 = typeof React.use === 'function'
26+
2427
export function createWebpackAliases({
2528
distDir,
2629
isClient,
@@ -90,6 +93,12 @@ export function createWebpackAliases({
9093
return {
9194
'@vercel/og$': 'next/dist/server/og/image-response',
9295

96+
// Avoid bundling both entrypoints in React 19 when we just need one.
97+
// Also avoids bundler warnings in React 18 where react-dom/server.edge doesn't exist.
98+
'next/dist/server/ReactDOMServerPages': isReact19
99+
? 'react-dom/server.edge'
100+
: 'react-dom/server.browser',
101+
93102
// Alias next/dist imports to next/dist/esm assets,
94103
// let this alias hit before `next` alias.
95104
...(isEdgeServer

packages/next/src/build/webpack-config.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,14 +1974,6 @@ export default async function getBaseWebpackConfig(
19741974
)
19751975
),
19761976
].filter(Boolean as any as ExcludesFalse),
1977-
ignoreWarnings: [
1978-
(warning) => {
1979-
// require('react-dom/server.edge') is wrapped in try-catch so save to ignore.
1980-
return warning.message.startsWith(
1981-
'Module not found: Error: Package path ./server.edge is not exported from package'
1982-
)
1983-
},
1984-
],
19851977
}
19861978

19871979
// Support tsconfig and jsconfig baseUrl

packages/next/src/server/render.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import type { Revalidate, SwrDelta } from './lib/revalidate'
4040
import type { COMPILER_NAMES } from '../shared/lib/constants'
4141

4242
import React, { type JSX } from 'react'
43-
import ReactDOMServerPages from './ReactDOMServerPages'
43+
import ReactDOMServerPages from 'next/dist/server/ReactDOMServerPages'
4444
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
4545
import {
4646
GSP_NO_RETURNED_VALUE,

packages/next/types/$$compiled.internal.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ declare module 'VAR_USERLAND'
3737
declare module 'VAR_MODULE_DOCUMENT'
3838
declare module 'VAR_MODULE_APP'
3939

40+
declare module 'next/dist/server/ReactDOMServerPages' {
41+
export * from 'react-dom/server.edge'
42+
}
43+
4044
declare module 'next/dist/compiled/@napi-rs/triples' {
4145
export * from '@napi-rs/triples'
4246
}

packages/next/types/react-dom.d.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,6 @@ declare module 'react-dom/server.edge' {
7070
>
7171
}
7272

73-
declare module 'react-dom/server.browser' {
74-
export * from 'react-dom/server.edge'
75-
}
76-
7773
declare module 'react-dom/static.edge' {
7874
import type { JSX } from 'react'
7975
/**

test/development/basic/next-rs-api.test.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import type {
1414
import loadConfig from 'next/dist/server/config'
1515
import path from 'path'
1616

17-
const isReact18 = parseInt(process.env.NEXT_TEST_REACT_VERSION) === 18
18-
1917
function normalizePath(path: string) {
2018
return path
2119
.replace(/\[project\].+\/node_modules\//g, '[project]/.../node_modules/')
@@ -42,21 +40,6 @@ function styledStringToMarkdown(styled: StyledString): string {
4240
}
4341
}
4442

45-
function isReactDOMServerEdgeConditionalBundlingIssue(issue: {
46-
description?: Issue['description']
47-
filePath: string
48-
}) {
49-
return (
50-
isReact18 &&
51-
issue.filePath ===
52-
'[project]/.../node_modules/next/dist/esm/server/ReactDOMServerPages.js' &&
53-
issue.description?.type === 'text' &&
54-
issue.description?.value.includes(
55-
'Import map: aliased to module "react-dom" with subpath "/server.edge" inside of [project]/'
56-
)
57-
)
58-
}
59-
6043
function normalizeIssues(issues: Issue[]) {
6144
return issues
6245
.map((issue) => ({
@@ -69,11 +52,6 @@ function normalizeIssues(issues: Issue[]) {
6952
source: normalizePath(issue.source.source.ident),
7053
},
7154
}))
72-
.filter((issue) => {
73-
// The conditional bundling is wrapped in a try-catch.
74-
// It doesn't surface to the user, so it's safe to ignore here.
75-
return !isReactDOMServerEdgeConditionalBundlingIssue(issue)
76-
})
7755
.sort((a, b) => {
7856
const a_ = JSON.stringify(a)
7957
const b_ = JSON.stringify(b)

0 commit comments

Comments
 (0)