Codemods
Codemods are transformations that run on your codebase programmatically. This allows a large number of changes to be programmatically applied without having to manually go through every file.
Next.js provides Codemod transformations to help upgrade your Next.js codebase when an API is updated or deprecated.
Usage
In your terminal, navigate (cd
) into your project's folder, then run:
npx @next/codemod <transform> <path>
Replacing <transform>
and <path>
with appropriate values.
transform
- name of transformpath
- files or directory to transform--dry
Do a dry-run, no code will be edited--print
Prints the changed output for comparison
Codemods
15.0
Transform App Router Route Segment Config runtime
value from experimental-edge
to edge
app-dir-runtime-config-experimental-edge
Note: This codemod is App Router specific.
npx @next/codemod@latest app-dir-runtime-config-experimental-edge .
This codemod transforms Route Segment Config runtime
value experimental-edge
to edge
.
For example:
export const runtime = 'experimental-edge'
Transforms into:
export const runtime = 'edge'
Migrate to async Dynamic APIs
APIs that opted into dynamic rendering that previously supported synchronous access are now asynchronous. You can read more about this breaking change in the upgrade guide.
next-async-request-api
npx @next/codemod@latest next-async-request-api .
This codemod will transform dynamic APIs (cookies()
, headers()
and draftMode()
from next/headers
) that are now asynchronous to be properly awaited or wrapped with React.use()
if applicable.
When an automatic migration isn't possible, the codemod will either add a typecast (if a TypeScript file) or a comment to inform the user that it needs to be manually reviewed & updated.
For example:
import { cookies, headers } from 'next/headers'
const token = cookies().get('token')
function useToken() {
const token = cookies().get('token')
return token
}
export default function Page() {
const name = cookies().get('name')
}
function getHeader() {
return headers().get('x-foo')
}
Transforms into:
import { use } from 'react'
import { cookies, headers, type UnsafeUnwrappedCookies } from 'next/headers'
const token = (await cookies()).get('token')
function useToken() {
const token = use(cookies()).get('token')
return token
}
export default function Page() {
const name = (await cookies()).get('name')
}
function getHeader() {
return (headers() as UnsafeUnwrappedCookies).get('x-foo')
}
When we detect property access on the params
or searchParams
props in the page / route entries (page.js
, layout.js
, route.js
, or default.js
) or the generateMetadata
/ generateViewport
APIs,
it will attempt to transform the callsite from a sync to an async function, and await the property access. If it can't be made async (such as with a client component), it will use React.use
to unwrap the promise .
For example:
// page.tsx
export default function Page({
params,
searchParams,
}: {
params: { slug: string }
searchParams: { [key: string]: string | string[] | undefined }
}) {
const { value } = searchParams
if (value === 'foo') {
// ...
}
}
export function generateMetadata({ params }: { params: { slug: string } }) {
return {
title: `My Page - ${slug}`,
}
}
Transforms into:
// page.tsx
export default function Page(props: {
params: { slug: string }
searchParams: { [key: string]: string | string[] | undefined }
}) {
const { value } = await props.searchParams
if (value === 'foo') {
// ...
}
}
export function generateMetadata(props: { params: { slug: string } }) {
const { slug } = await props.params
return {
title: `My Page - ${slug}`,
}
}
Good to know: When this codemod identifies a spot that might require manual intervention, but we aren't able to determine the exact fix, it will add a comment or typecast to the code to inform the user that it needs to be manually updated. These comments are prefixed with @next/codemod, and typecasts are prefixed with
UnsafeUnwrapped
. Your build will error until these comments are explicitly removed. Read more.
Replace geo
and ip
properties of NextRequest
with @vercel/functions
next-request-geo-ip
npx @next/codemod@latest next-request-geo-ip .
This codemod installs @vercel/functions
and transforms geo
and ip
properties of NextRequest
with corresponding @vercel/functions
features.
For example:
import type { NextRequest } from 'next/server'
export function GET(req: NextRequest) {
const { geo, ip } = req
}
Transforms into:
import type { NextRequest } from 'next/server'
import { geolocation, ipAddress } from '@vercel/functions'
export function GET(req: NextRequest) {
const geo = geolocation(req)
const ip = ipAddress(req)
}
14.0
Migrate ImageResponse
imports
next-og-import
npx @next/codemod@latest next-og-import .
This codemod moves transforms imports from next/server
to next/og
for usage of Dynamic OG Image Generation.
For example:
import { ImageResponse } from 'next/server'
Transforms into:
import { ImageResponse } from 'next/og'
Use viewport
export
metadata-to-viewport-export
npx @next/codemod@latest metadata-to-viewport-export .
This codemod migrates certain viewport metadata to viewport
export.
For example:
export const metadata = {
title: 'My App',
themeColor: 'dark',
viewport: {
width: 1,
},
}
Transforms into:
export const metadata = {
title: 'My App',
}
export const viewport = {
width: 1,
themeColor: 'dark',
}
13.2
Use Built-in Font
built-in-next-font
npx @next/codemod@latest built-in-next-font .
This codemod uninstalls the @next/font
package and transforms @next/font
imports into the built-in next/font
.
For example:
import { Inter } from '@next/font/google'
Transforms into:
import { Inter } from 'next/font/google'
13.0
Rename Next Image Imports
next-image-to-legacy-image
npx @next/codemod@latest next-image-to-legacy-image .
Safely renames next/image
imports in existing Next.js 10, 11, or 12 applications to next/legacy/image
in Next.js 13. Also renames next/future/image
to next/image
.
For example:
import Image1 from 'next/image'
import Image2 from 'next/future/image'
export default function Home() {
return (
<div>
<Image1 src="/test.jpg" width="200" height="300" />
<Image2 src="/test.png" width="500" height="400" />
</div>
)
}
Transforms into:
// 'next/image' becomes 'next/legacy/image'
import Image1 from 'next/legacy/image'
// 'next/future/image' becomes 'next/image'
import Image2 from 'next/image'
export default function Home() {
return (
<div>
<Image1 src="/test.jpg" width="200" height="300" />
<Image2 src="/test.png" width="500" height="400" />
</div>
)
}
Migrate to the New Image Component
next-image-experimental
npx @next/codemod@latest next-image-experimental .
Dangerously migrates from next/legacy/image
to the new next/image
by adding inline styles and removing unused props.
- Removes
layout
prop and addsstyle
. - Removes
objectFit
prop and addsstyle
. - Removes
objectPosition
prop and addsstyle
. - Removes
lazyBoundary
prop. - Removes
lazyRoot
prop.
Remove <a>
Tags From Link Components
new-link
npx @next/codemod@latest new-link .
Remove <a>
tags inside Link Components, or add a legacyBehavior
prop to Links that cannot be auto-fixed.
For example:
<Link href="/about">
<a>About</a>
</Link>
// transforms into
<Link href="/about">
About
</Link>
<Link href="/about">
<a onClick={() => console.log('clicked')}>About</a>
</Link>
// transforms into
<Link href="/about" onClick={() => console.log('clicked')}>
About
</Link>
In cases where auto-fixing can't be applied, the legacyBehavior
prop is added. This allows your app to keep functioning using the old behavior for that particular link.
const Component = () => <a>About</a>
<Link href="/about">
<Component />
</Link>
// becomes
<Link href="/about" legacyBehavior>
<Component />
</Link>
11
Migrate from CRA
cra-to-next
npx @next/codemod cra-to-next
Migrates a Create React App project to Next.js; creating a Pages Router and necessary config to match behavior. Client-side only rendering is leveraged initially to prevent breaking compatibility due to window
usage during SSR and can be enabled seamlessly to allow the gradual adoption of Next.js specific features.
Please share any feedback related to this transform in this discussion.
10
Add React imports
add-missing-react-import
npx @next/codemod add-missing-react-import
Transforms files that do not import React
to include the import in order for the new React JSX transform to work.
For example:
export default class Home extends React.Component {
render() {
return <div>Hello World</div>
}
}
Transforms into:
import React from 'react'
export default class Home extends React.Component {
render() {
return <div>Hello World</div>
}
}
9
Transform Anonymous Components into Named Components
name-default-component
npx @next/codemod name-default-component
Versions 9 and above.
Transforms anonymous components into named components to make sure they work with Fast Refresh.
For example:
export default function () {
return <div>Hello World</div>
}
Transforms into:
export default function MyComponent() {
return <div>Hello World</div>
}
The component will have a camel-cased name based on the name of the file, and it also works with arrow functions.
8
Transform AMP HOC into page config
withamp-to-config
npx @next/codemod withamp-to-config
Transforms the withAmp
HOC into Next.js 9 page configuration.
For example:
// Before
import { withAmp } from 'next/amp'
function Home() {
return <h1>My AMP Page</h1>
}
export default withAmp(Home)
// After
export default function Home() {
return <h1>My AMP Page</h1>
}
export const config = {
amp: true,
}
6
Use withRouter
url-to-withrouter
npx @next/codemod url-to-withrouter
Transforms the deprecated automatically injected url
property on top level pages to using withRouter
and the router
property it injects. Read more here: https://nextjs.org/docs/messages/url-deprecated
For example:
import React from 'react'
export default class extends React.Component {
render() {
const { pathname } = this.props.url
return <div>Current pathname: {pathname}</div>
}
}
import React from 'react'
import { withRouter } from 'next/router'
export default withRouter(
class extends React.Component {
render() {
const { pathname } = this.props.router
return <div>Current pathname: {pathname}</div>
}
}
)
This is one case. All the cases that are transformed (and tested) can be found in the __testfixtures__
directory.
Was this helpful?