-
Notifications
You must be signed in to change notification settings - Fork 26.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(next-upgrade): suggest React codemod #71016
Merged
devjiwonchoi
merged 15 commits into
canary
from
10-09-feat_next-upgrade_suggest_react_codemod
Oct 11, 2024
Merged
Changes from 6 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
68efe5f
feat(next-upgrade): suggest React codemod
devjiwonchoi c84bcd2
add react-types codemod
devjiwonchoi 3be684d
add refs
devjiwonchoi ba167ae
Merge branch 'canary' into 10-09-feat_next-upgrade_suggest_react_codemod
devjiwonchoi f28c651
Update packages/next-codemod/bin/upgrade.ts
devjiwonchoi 6d563dd
chore: prompt user whether is using pages only and want react 18
devjiwonchoi 9b6db24
Apply suggestions from code review
devjiwonchoi 6a1de7c
chore: ternary truthy
devjiwonchoi 0fa6515
apply codemods after all prompts
devjiwonchoi ba74ee2
prompt user to stay on react only if react still 18 but is over canar…
devjiwonchoi 6b72bda
fix: uncomment exec command, run react codemod only when 19+
devjiwonchoi 51bbc4a
Apply suggestions from code review
devjiwonchoi 8744dbc
Apply suggestions from code review
devjiwonchoi 980b683
fix: missed quote
devjiwonchoi 00e39a6
Merge branch 'canary' into 10-09-feat_next-upgrade_suggest_react_codemod
devjiwonchoi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,14 +74,31 @@ export async function runUpgrade( | |
return | ||
} | ||
|
||
// If the app is a pure Pages Router (no app dir) and the user wants to stay on React 18, | ||
// we can skip the upgrading React and suggesting relevant codemods. | ||
const { isPagesOnlyAndWantReact18 } = await prompts( | ||
{ | ||
type: 'confirm', | ||
name: 'isPagesOnlyAndWantReact18', | ||
message: | ||
'Are you using Pages Router only (no App Router) and want to upgrade up until React 18?', | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having a hard time understanding what this prompt is asking. |
||
initial: false, | ||
active: 'Yes', | ||
inactive: 'No', | ||
}, | ||
{ onCancel } | ||
) | ||
|
||
// We're resolving a specific version here to avoid including "ugly" version queries | ||
// in the manifest. | ||
// E.g. in peerDependencies we could have `^18.2.0 || ^19.0.0 || 20.0.0-canary` | ||
// If we'd just `npm add` that, the manifest would read the same version query. | ||
// This is basically a `npm --save-exact react@$versionQuery` that works for every package manager. | ||
const targetReactVersion = await loadHighestNPMVersionMatching( | ||
`react@${targetNextPackageJson.peerDependencies['react']}` | ||
) | ||
const targetReactVersion = !isPagesOnlyAndWantReact18 | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
? await loadHighestNPMVersionMatching( | ||
`react@${targetNextPackageJson.peerDependencies['react']}` | ||
) | ||
: '18.3.0' | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (compareVersions(targetNextVersion, '15.0.0-canary') >= 0) { | ||
await suggestTurbopack(appPackageJson) | ||
|
@@ -134,6 +151,12 @@ export async function runUpgrade( | |
await runTransform(codemod, process.cwd(), { force: true }) | ||
} | ||
|
||
// The following React codemods are for React 19 | ||
if (!isPagesOnlyAndWantReact18) { | ||
await suggestReactCodemods(packageManager) | ||
await suggestReactTypesCodemods(packageManager) | ||
} | ||
|
||
console.log() // new line | ||
if (codemods.length > 0) { | ||
console.log(`${pc.green('✔')} Codemods have been applied successfully.`) | ||
|
@@ -263,3 +286,61 @@ async function suggestCodemods( | |
|
||
return codemods | ||
} | ||
|
||
async function suggestReactCodemods(packageManager: PackageManager) { | ||
const { runReactCodemod } = await prompts( | ||
{ | ||
type: 'toggle', | ||
name: 'runReactCodemod', | ||
message: 'Do you want to run the React 19 upgrade codemod?', | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
initial: true, | ||
active: 'Yes', | ||
inactive: 'No', | ||
}, | ||
{ onCancel } | ||
) | ||
|
||
if (runReactCodemod) { | ||
const commandMap = { | ||
yarn: 'yarn dlx', | ||
pnpm: 'pnpx', | ||
bun: 'bunx', | ||
npm: 'npx', | ||
} | ||
const command = commandMap[packageManager] || 'npx' | ||
|
||
// https://react.dev/blog/2024/04/25/react-19-upgrade-guide#run-all-react-19-codemods | ||
execSync(`${command} codemod@latest react/19/migration-recipe`, { | ||
stdio: 'inherit', | ||
}) | ||
} | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
async function suggestReactTypesCodemods(packageManager: PackageManager) { | ||
const { runReactTypesCodemod } = await prompts( | ||
{ | ||
type: 'toggle', | ||
name: 'runReactTypesCodemod', | ||
message: 'Do you want to run the React Types codemod?', | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
initial: true, | ||
active: 'Yes', | ||
inactive: 'No', | ||
}, | ||
{ onCancel } | ||
) | ||
|
||
if (runReactTypesCodemod) { | ||
const commandMap = { | ||
yarn: 'yarn dlx', | ||
pnpm: 'pnpx', | ||
bun: 'bunx', | ||
npm: 'npx', | ||
} | ||
const command = commandMap[packageManager] || 'npx' | ||
|
||
// https://react.dev/blog/2024/04/25/react-19-upgrade-guide#typescript-changes | ||
execSync(`${command} types-react-codemod@latest preset-19 .`, { | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
stdio: 'inherit', | ||
}) | ||
devjiwonchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's only ask that if you're above .45 and still have 18 installed. Saves one prompt for the good citizen who are on 19.
Technically you can't withhold if you're between .45 and whatever version we landed support for React 18 in pages router (.169?) but that's not really a version range we need to be concerned with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you find your request resolved?