Руководство по переходу на Next.js 16: пошаговая миграция
Обновление Next.js-проекта между мажорными версиями редко ограничивается запуском npm install next@latest. Особенно если речь идёт о production-приложении, в котором используются authentication, middleware, caching, image optimization или собственные настройки сборки. В таком случае обновление фреймворка может напрямую затронуть архитектуру приложения.
Next.js 16 — именно такой релиз.
Первая версия Next.js 16 вышла в октябре 2025 года. В ней Turbopack стал bundler по умолчанию, была переработана модель кэширования, появилась поддержка React Compiler, были улучшены механизмы routing, а также добавлены breaking changes, которые могут потребовать непосредственных изменений в коде. Развитие ветки 16 продолжилось: 3 августа 2026 года вышел Next.js 16.3 с дополнительными улучшениями производительности и developer experience.
Поэтому в этой статье мы не будем ограничиваться вопросом «Что нового в Next.js 16?». Гораздо важнее другой вопрос:
Что может сломаться при переходе существующего проекта с Next.js 15 на Next.js 16 и как провести миграцию контролируемо?
Сначала проверим окружение
Перед началом миграции я в первую очередь смотрю не на сам фреймворк, а на рабочее окружение. Причина проста: в Next.js 16 изменились минимальные системные требования.
Для Next.js 16 требуется как минимум Node.js 20.9.0 и TypeScript 5.1.0. Node.js 18 больше не поддерживается.
Сначала проверим текущую версию Node.js:
node -v
Если проект использует Docker, обновить только локальное окружение недостаточно. Необходимо также проверить Node image в Dockerfile, CI/CD pipeline и версию Node.js на production-сервере.
Например, если старый Dockerfile выглядит так:
FROM node:18-alpine
при переходе на Next.js 16 его необходимо перевести на поддерживаемую версию Node 20.
Это одна из тех проблем, которые особенно легко пропустить при major migration: локально приложение работает нормально, а production build по-прежнему выполняется на старой версии Node.js.

Как обновиться до Next.js 16?
Команда Next.js предоставляет специальный codemod для миграции.
Если используется npm:
npx @next/codemod@canary upgrade latest
Если вы хотите выполнить обновление вручную:
npm install next@latest react@latest react-dom@latest
Для проектов на TypeScript также следует обновить пакеты типов React:
npm install -D @types/react@latest @types/react-dom@latest
По возможности я предпочитаю начинать именно с codemod. Codemod для v16 не просто меняет версии dependencies: он может обновить Turbopack configuration, перенести использование next lint на ESLint CLI, преобразовать convention middleware в proxy и удалить некоторые устаревшие experimental-настройки.
Но здесь есть важный момент:
Codemod упрощает миграцию, но не выполняет её полностью вместо вас.
Custom Webpack configuration, сторонние библиотеки, authentication layer и поведение caching всё равно необходимо тестировать вручную.
Turbopack теперь используется по умолчанию
На мой взгляд, это одно из самых важных изменений при переходе на Next.js 16.
Начиная с Next.js 16, Turbopack используется по умолчанию и для next dev, и для next build. Передавать --turbo или --turbopack отдельно больше не нужно.
Раньше:
{
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack"
}
}
Теперь:
{
"scripts": {
"dev": "next dev",
"build": "next build"
}
}
Основные сложности начинаются в проектах с custom Webpack configuration.
Если в next.config.js определена собственная функция webpack(), автоматический переход Next.js 16 на Turbopack может привести к неожиданному поведению. В некоторых случаях Next.js может остановить build, чтобы не продолжать сборку с несовместимой конфигурацией.
Если необходимо продолжать использовать Webpack:
next dev --webpack
next build --webpack
Turbopack уже достаточно зрелый, однако он всё ещё не является полной копией plugin ecosystem Webpack. Поэтому в крупных проектах с Sentry, custom loaders, собственными Sass-процессами или другими Webpack plugins необходимо отдельно проверить эти интеграции.
Я бы не стал придерживаться подхода «появился Turbopack — сразу удаляем Webpack». Сначала лучше сравнить development и production build с обоими bundler.
params, searchParams, cookies() и headers() теперь полностью асинхронные
Next.js 15 уже начал подготавливать разработчиков к этому изменению.
Такие request-time API, как params, searchParams, cookies(), headers() и draftMode(), стали асинхронными ещё в Next.js 15. Однако для обратной совместимости некоторое время сохранялась возможность синхронного использования.
В Next.js 16 эта возможность полностью удалена.
Например, раньше можно было встретить такой код:
export default function Page({
params,
}: {
params: { slug: string }
}) {
const { slug } = params
return <div>{slug}</div>
}
В Next.js 16 его необходимо изменить:
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <div>{slug}</div>
}
То же самое касается cookies().
Старый вариант:
import { cookies } from 'next/headers'
const cookieStore = cookies()
const token = cookieStore.get('token')
Новый вариант:
import { cookies } from 'next/headers'
const cookieStore = await cookies()
const token = cookieStore.get('token')
В крупном App Router проекте после migration я бы проверил такие использования в первую очередь.
Причём речь идёт не только о page.tsx. params могут использоваться в layouts, Route Handlers, generateMetadata, Open Graph image routes и других частях приложения.
Next.js также позволяет сгенерировать type helper'ы PageProps, LayoutProps и RouteContext:
npx next typegen
middleware.ts уступает место proxy.ts
Ещё одно заметное изменение связано с naming convention.
В Next.js 16 middleware.ts объявлен deprecated, а вместо него используется proxy.ts. Идея состоит в том, чтобы яснее показать: этот слой не является универсальным Express-подобным middleware, а работает на network boundary перед приложением.
Раньше:
// middleware.ts
export function middleware(request: NextRequest) {
// ...
}
Теперь:
// proxy.ts
export function proxy(request: NextRequest) {
// ...
}
Для миграции есть отдельный codemod:
npx @next/codemod@canary middleware-to-proxy .
Меняется не только имя файла. Экспортируемую функцию middleware также рекомендуется переименовать в proxy.
Но более важный момент связан с runtime.
proxy.ts работает в Node.js runtime, и изменить runtime вручную нельзя. Поэтому существующие Middleware implementation, зависящие от Edge runtime, необходимо оценивать отдельно.
Особенно внимательно следует тестировать проекты, где Middleware активно используется для authentication, locale redirects, rewrite или authorization.
next lint больше нет
Изменение выглядит небольшим, но легко может сломать CI pipeline.
В Next.js 16 удалена команда:
next lint
Кроме того, next build больше не запускает lint автоматически. Процесс linting теперь отделён от framework build, а проекты должны использовать ESLint CLI напрямую.
Если в package.json есть:
{
"scripts": {
"lint": "next lint"
}
}
его можно заменить, например, на:
{
"scripts": {
"lint": "eslint ."
}
}
Codemod также может помочь с этим преобразованием.
Если в CI/CD перед build выполняется npm run lint, обязательно добавьте этот пункт в migration checklist.
Изменились значения по умолчанию в next/image
Next.js 16 также меняет некоторые defaults, связанные с image optimization.
Например, значение images.minimumCacheTTL по умолчанию увеличено с 60 секунд до 4 часов. Кроме того, вместо более широкого диапазона качества изображений значением по умолчанию теперь является только [75].
Если в проекте используется:
<Image
src="/product.jpg"
width={800}
height={600}
quality={100}
alt="Product"
/>
и необходимо сохранить quality={100}, это значение может потребоваться явно указать в configuration:
const nextConfig = {
images: {
qualities: [50, 75, 100],
},
}
export default nextConfig
Ещё один breaking change связан с query string в локальных image URL.
Например:
<Image
src="/assets/product.jpg?v=2"
width={500}
height={500}
alt="Product"
/>
Для подобных URL теперь может потребоваться соответствующая настройка images.localPatterns.
Особенно важно проверить этот момент в e-commerce и CMS-проектах, где URL изображений часто формируются динамически.
Cache Components делают кэширование более явным
Caching был одной из самых запутанных тем в последних major-версиях Next.js.
«Почему этот fetch закэшировался?», «Почему route стал static?», «Почему revalidation не отобразился сразу?» — с такими вопросами сталкивался практически каждый, кто работал с App Router.
В Next.js 16 модель становится более explicit.
Cache Components можно включить:
const nextConfig = {
cacheComponents: true,
}
export default nextConfig
После этого directive "use cache" позволяет более явно управлять тем, какие component или function должны кэшироваться. Предыдущий подход experimental.ppr также перенесён в модель Cache Components.
Здесь важно понимать следующее:
Для перехода на Next.js 16 необязательно сразу использовать Cache Components.
Во время migration я бы не стал полностью переписывать caching architecture в том же commit. Сначала лучше стабилизировать переход на новую версию framework, а Cache Components рассматривать как отдельную задачу.
Если одновременно выполнять major migration и менять caching architecture, при возникновении ошибки будет значительно сложнее понять её источник.
revalidateTag() изменился, появился updateTag()
На уровне caching API также произошли важные изменения.
Для revalidateTag() теперь рекомендуется использовать второй параметр с профилем cacheLife:
import { revalidateTag } from 'next/cache'
revalidateTag('blog-posts', 'max')
Такой подход помечает текущий cache как stale по модели stale-while-revalidate, после чего актуальные данные загружаются в background.
Вариант с одним аргументом теперь deprecated.
Next.js 16 также добавляет API updateTag().
'use server'
import { updateTag } from 'next/cache'
export async function updateProfile() {
// database update
updateTag('user-profile')
}
updateTag() предназначен для сценариев, когда пользователь должен сразу увидеть актуальные данные после внесённого изменения. API можно использовать только внутри Server Actions.
Я бы разделял их следующим образом:
Для блога, каталога или документации, где задержка в несколько секунд не критична, использовать revalidateTag(). Когда пользователь должен сразу увидеть только что внесённое изменение — updateTag().
React Compiler теперь Stable, но включать его необязательно
В Next.js 16 поддержка React Compiler получила статус stable.
React Compiler автоматически memoize компоненты, снижая количество ненужных render. Однако по умолчанию он отключён.
Для включения:
const nextConfig = {
reactCompiler: true,
}
export default nextConfig
Также необходимо установить пакет compiler:
npm install -D babel-plugin-react-compiler
Во время migration я бы применял тот же принцип:
Сначала завершить переход на Next.js 16 и проверить application behavior, а затем отдельно рассматривать React Compiler как optimization step.
React Compiler добавляет дополнительную нагрузку на build pipeline, поэтому development и production build могут занимать больше времени.
Что проверить после миграции на Next.js 16?
То, что код успешно compile, ещё не означает, что migration завершена.
Перед production deployment я бы обязательно проверил:
- Используются ли поддерживаемые версии Node.js, TypeScript, React и Next.js?
- Корректно ли работают development и production build с Turbopack?
- Проверена ли совместимость custom Webpack configuration с Turbopack?
- Удалены ли синхронные использования
params,searchParams,cookies(),headers()иdraftMode()? - Проверена ли миграция с
middleware.tsнаproxy.ts? - Корректно ли работают authentication, redirects, rewrites и locale routing?
- Обновлены ли scripts и CI pipeline, использующие
next lint? - Проверены ли quality, cache и local URL в
next/image? - Работают ли ISR, cache invalidation и обновление данных после Server Actions?
- Проверены ли dynamic routes и
generateMetadata? - Проверены ли критические production-страницы с помощью Lighthouse и реальных пользовательских сценариев?
Также намного безопаснее выполнять migration в отдельной branch и сравнивать новый build Next.js 16 с существующим Next.js 15, а не обновлять production branch напрямую.
Как лучше выстроить переход на Next.js 16?
Переход на новую major-версию не должен быть самоцелью. Для активно развивающегося Next.js-приложения, которое будет использоваться ещё долго, поддержание актуальной версии может дать важные преимущества с точки зрения security updates, развития framework и поддержки ecosystem.
Однако незапланированная migration может создать лишние риски в крупных production-приложениях, которые сильно зависят от custom Webpack plugins, Edge Middleware или старого поведения framework.
Поэтому major version migration лучше рассматривать не как обычное обновление dependency, а как отдельную небольшую техническую задачу.
На первый взгляд Next.js 16 привлекает внимание такими возможностями, как Turbopack, React Compiler и Cache Components. Но при migration существующего проекта основное внимание следует уделить breaking changes.
Turbopack по умолчанию влияет на build pipeline, async Request API — на App Router code, переход на proxy.ts — на request layer, изменения ESLint — на CI/CD, а новые caching API могут напрямую влиять на стратегию обновления данных.
Наиболее безопасная последовательность выглядит просто:
Сначала совместимость, затем migration и только после этого оптимизация.
Сначала следует обновить dependencies и рабочее окружение, затем устранить breaking changes и убедиться, что существующее поведение приложения не изменилось. Такие возможности, как Turbopack, Cache Components и React Compiler, лучше подключать постепенно уже после стабилизации migration.
Потому что переход на Next.js 16 и одновременное использование всех новых возможностей Next.js 16 — не одно и то же.
Благодаря codemod и upgrade-инструментам Next.js переход с Next.js 15 на 16 при правильной последовательности действий не обязательно должен быть сложным или болезненным.
Если вам необходимо разработать масштабируемое и производительное веб-приложение на современных технологиях или модернизировать техническую инфраструктуру существующего проекта, Detartech может комплексно реализовать эту задачу с помощью своих решений в области веб-разработки.

