Skip to content

Commit 4b364ca

Browse files
authored
next-upgrade: Stop prompting for React 19 upgrade on pure App Router apps (#71486)
1 parent a4840e3 commit 4b364ca

File tree

10 files changed

+38
-11
lines changed

10 files changed

+38
-11
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Prompts for React 19 upgrade
1+
Prompts for React 19 upgrade with a recommendation to do so

packages/next-codemod/bin/__testfixtures__/react-18-installed-mixed-router/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-18-installed-mixed-router",
33
"scripts": {
4-
"dev": "next dev"
4+
"dev": "next dev --turbo"
55
},
66
"dependencies": {
77
"next": "14.3.0-canary.44",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Prompts for React 19 upgrade
1+
Upgrades to React 19 automatically

packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-app-router/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-18-installed-pure-app-router",
33
"scripts": {
4-
"dev": "next dev"
4+
"dev": "next dev --turbo"
55
},
66
"dependencies": {
77
"next": "14.3.0-canary.44",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Prompts for React 19 upgrade
1+
Prompts for React 19 upgrade without any recommendation

packages/next-codemod/bin/__testfixtures__/react-18-installed-pure-pages-router/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-18-installed-pure-pages-router",
33
"scripts": {
4-
"dev": "next dev"
4+
"dev": "next dev --turbo"
55
},
66
"dependencies": {
77
"next": "14.3.0-canary.44",

packages/next-codemod/bin/__testfixtures__/react-19-installed-mixed-router/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-19-installed-mixed-router",
33
"scripts": {
4-
"dev": "next dev"
4+
"dev": "next dev --turbo"
55
},
66
"dependencies": {
77
"next": "14.3.0-canary.45",

packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-app-router/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-19-installed-pure-app-router",
33
"scripts": {
4-
"dev": "next dev"
4+
"dev": "next dev --turbo"
55
},
66
"dependencies": {
77
"next": "14.3.0-canary.45",

packages/next-codemod/bin/__testfixtures__/react-19-installed-pure-pages-router/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-19-installed-pure-pages-router",
33
"scripts": {
4-
"dev": "next dev"
4+
"dev": "next dev --turbo"
55
},
66
"dependencies": {
77
"next": "14.3.0-canary.45",

packages/next-codemod/bin/upgrade.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ export async function runUpgrade(
125125
console.log(` - React: v${installedReactVersion}`)
126126
console.log(` - Next.js: v${installedNextVersion}`)
127127
let shouldStayOnReact18 = false
128+
129+
const usesAppDir = isUsingAppDir(process.cwd())
130+
const usesPagesDir = isUsingPagesDir(process.cwd())
131+
132+
const isPureAppRouter = usesAppDir && !usesPagesDir
133+
const isMixedApp = usesPagesDir && usesAppDir
128134
if (
129135
// From release v14.3.0-canary.45, Next.js expects the React version to be 19.0.0-beta.0
130136
// If the user is on a version higher than this but is still on React 18, we ask them
@@ -134,13 +140,21 @@ export async function runUpgrade(
134140
// x-ref(PR): https://github.com/vercel/next.js/pull/65058
135141
// x-ref(release): https://github.com/vercel/next.js/releases/tag/v14.3.0-canary.45
136142
compareVersions(targetNextVersion, '14.3.0-canary.45') >= 0 &&
137-
installedReactVersion.startsWith('18')
143+
installedReactVersion.startsWith('18') &&
144+
// Pure App Router always uses React 19
145+
// The mixed case is tricky to handle from a types perspective.
146+
// We'll recommend to upgrade in the prompt but users can decide to try 18.
147+
!isPureAppRouter
138148
) {
139149
const shouldStayOnReact18Res = await prompts(
140150
{
141151
type: 'confirm',
142152
name: 'shouldStayOnReact18',
143-
message: `Are you using ${pc.underline('only the Pages Router')} (no App Router) and prefer to stay on React 18?`,
153+
message:
154+
`Do you prefer to stay on React 18?` +
155+
(isMixedApp
156+
? " Since you're using both pages/ and app/, we recommend upgrading React to use a consistent version throughout your app."
157+
: ''),
144158
initial: false,
145159
active: 'Yes',
146160
inactive: 'No',
@@ -371,6 +385,19 @@ function getInstalledReactVersion(): string {
371385
}
372386
}
373387

388+
function isUsingPagesDir(projectPath: string): boolean {
389+
return (
390+
fs.existsSync(path.resolve(projectPath, 'pages')) ||
391+
fs.existsSync(path.resolve(projectPath, 'src/pages'))
392+
)
393+
}
394+
function isUsingAppDir(projectPath: string): boolean {
395+
return (
396+
fs.existsSync(path.resolve(projectPath, 'app')) ||
397+
fs.existsSync(path.resolve(projectPath, 'src/app'))
398+
)
399+
}
400+
374401
/*
375402
* Heuristics are used to determine whether to Turbopack is enabled or not and
376403
* to determine how to update the dev script.

0 commit comments

Comments
 (0)