NextJS 15. Что нового? - bekkaryuk.ru

NextJS 15. Что нового?

1 января 2025 11:51

Next.js 15

Перевод статьи с nextjs.org

Next.js 15 официально стабилен и готов к производству. Этот выпуск основан на обновлениях из RC1 и RC2. Мы уделили большое внимание стабильности и добавили несколько интересных обновлений, которые, как мы думаем, вам понравятся.

Плавное обновление с помощью @next/codemod CLI

Мы включаем codemods (автоматические преобразования кода) в каждый крупный релиз Next.js, чтобы помочь автоматизировать обновление изменений.

Чтобы сделать обновление еще более плавным, мы выпустили улучшенный codemod CLI:

npx @next/codemod@canary upgrade latest

Этот инструмент поможет вам обновить кодовую базу до последних стабильных или предрелизных версий. CLI обновит ваши зависимости, покажет доступные кодовые моды и проведет вас через их применение.

Тег canary использует последнюю версию codemod, а latest указывает на версию Next.js. Мы рекомендуем использовать canary-версию codemod, даже если вы обновляетесь до последней версии Next.js, так как мы планируем продолжать улучшать инструмент на основе ваших отзывов.

Узнайте больше о Next.js codemod CLI

API для асинхронных запросов

При традиционном серверном рендеринге сервер ожидает запроса, прежде чем отрисовать содержимое. Однако не все компоненты зависят от данных, специфичных для запроса, поэтому нет необходимости ждать запроса для их рендеринга. В идеале сервер должен подготовить как можно больше данных до поступления запроса. Чтобы обеспечить это и заложить основу для будущих оптимизаций, нам нужно знать, когда ждать запрос.

Поэтому мы переводим API, которые полагаются на данные, специфичные для запроса, такие как headers, cookies, params и searchParams в асинхронный режим.

import { cookies } from 'next/headers';
 
export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
 
  // ...
}

Это изменение является критическим и затрагивает следующие API:

  • cookies
  • headers
  • draftMode
  • params в layout.js, page.js, route.js, default.js, generateMetadata, и generateViewport
  • searchParams в page.js

Для облегчения миграции к этим API можно временно использовать синхронный доступ, но в разработке и на проде они будут показывать предупреждения до следующей основной версии. Для автоматизации миграции доступен codemod:

npx @next/codemod@canary next-async-request-api .

Для случаев, когда кодмод не может полностью перенести ваш код, пожалуйста, прочитайте руководство по обновлению. Мы также привели пример того, как перенести приложение Next.js на новые API.

Семантика кэширования

Next.js App Router был запущен с настройками кэширования по умолчанию. Они были разработаны для обеспечения наиболее производительного варианта по умолчанию с возможностью отказаться от него при необходимости.

Основываясь на ваших отзывах, мы пересмотрели наши эвристики кэширования и то, как они будут взаимодействовать с такими проектами, как Partial Prerendering (PPR), и со сторонними библиотеками, использующими fetch.

В Next.js 15 мы меняем кэширование по умолчанию для обработчиков маршрутов GET и кэша маршрутизатора клиента с кэширования по умолчанию на отсутствие кэширования по умолчанию. Если вы хотите сохранить прежнее поведение, вы можете отказаться от кэширования.

Мы продолжаем улучшать кэширование в Next.js в ближайшие месяцы и скоро поделимся более подробной информацией.

Обработчики маршрутов GET больше не кэшируются по умолчанию

В Next 14 обработчики маршрутов, использующие HTTP-метод GET, по умолчанию кэшировались, если в них не использовалась динамическая функция или динамический параметр конфигурации. В Next.js 15 функции GET не кэшируются по умолчанию.

Вы все еще можете отказаться от кэширования, используя опцию конфигурации статического маршрута, например export dynamic = 'force-static'.

Специальные обработчики маршрутов, такие как sitemap.ts, opengraph-image.tsx, icon.tsx, и другие файлы метаданных по умолчанию остаются статичными, если в них не используются динамические функции или динамические параметры конфигурации.

Client Router Cache больше не кэширует компоненты страницы по умолчанию

В Next.js 14.2.0 мы ввели экспериментальный флаг staleTimes, позволяющий настраивать кэш маршрутизатора.

В Next.js 15 этот флаг по-прежнему доступен, но мы меняем поведение по умолчанию, чтобы StaleTime для сегментов Page был равен 0. Это означает, что при навигации по приложению клиент всегда будет отражать последние данные от компонента(ов) Page, который(ые) становится(ятся) активным(и) в процессе навигации. Тем не менее, есть важные модели поведения, которые остаются неизменными:

  • Shared layout data won't be refetched from the server to continue to support partial rendering.
  • Back/forward navigation will still restore from cache to ensure the browser can restore scroll position.
  • loading.js will remain cached for 5 minutes (or the value of the staleTimes.static configuration).

Вы можете отказаться от предыдущего поведения Client Router Cache, задав следующую конфигурацию:

const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
    },
  },
};
 
export default nextConfig;

React 19

В рамках выпуска Next.js 15 мы приняли решение о согласовании с грядущим релизом React 19.

В версии 15 App Router использует React 19 RC, и мы также ввели обратную совместимость для React 18 с Pages Router, основываясь на отзывах сообщества. Если вы используете Pages Router, это позволит вам перейти на React 19, когда он будет готов.

Хотя React 19 все еще находится на стадии RC, наше обширное тестирование в реальных приложениях и тесное сотрудничество с командой React дают нам уверенность в его стабильности. Основные изменения были хорошо протестированы и не повлияют на существующих пользователей App Router. Поэтому мы решили выпустить Next.js 15 как стабильный, чтобы ваши проекты были полностью готовы к выходу React 19 GA.

Чтобы переход был как можно более плавным, мы подготовили автоматизированные инструменты для облегчения процесса миграции.

Прочитайте руководство по обновлению Next.js 15, руководство по обновлению React 19 и посмотрите выступление на React Conf Keynote, чтобы узнать больше.

Pages Router на React 18

Next.js 15 сохраняет обратную совместимость Pages Router с React 18, что позволяет пользователям продолжать использовать React 18, получая преимущества от улучшений в Next.js 15.

С момента выхода первого релиз-кандидата (RC1) мы сместили акцент на поддержку React 18, основываясь на отзывах сообщества. Благодаря этой гибкости вы можете перейти на Next.js 15 и использовать Pages Router с React 18, обеспечивая больший контроль над своим путем обновления.

Компилятор React (экспериментальный)

React Compiler - это новый экспериментальный компилятор, созданный командой React в Meta. Компилятор понимает ваш код на глубоком уровне благодаря пониманию семантики обычного JavaScript и правил React, что позволяет ему добавлять автоматические оптимизации в ваш код. Компилятор уменьшает количество ручных мемоизаций, которые приходится делать разработчикам, благодаря таким API, как useMemo и useCallback, что делает код проще, легче в сопровождении и менее подверженным ошибкам.

В Next.js 15 мы добавили поддержку компилятора React. Узнайте больше о компиляторе React и доступных опциях конфигурации Next.js.

Улучшение ошибок при гидратации

В Next.js 14.1 были улучшены сообщения об ошибках и ошибки гидратации. Next.js 15 продолжает их развивать, добавив улучшенное представление ошибок гидратации. Теперь ошибки гидратации отображают исходный код ошибки с предложениями по устранению проблемы.

Например, это предыдущее сообщение об ошибке гидратации в Next.js 14.1:

hydration error next 14

В Next.js 15 эта функция улучшена:

hydration error next 15

Turbopack Dev

Мы рады сообщить, что next dev --turbo теперь стабилен и готов ускорить вашу разработку. Мы используем его для итераций на vercel.com, nextjs.org, v0 и всех других наших приложениях с отличными результатами.

Например, на сайте vercel.com, крупном приложении Next.js, мы увидели:

  • До 76,7% быстрее запуск локального сервера.
  • До 96,3% быстрее обновление кода с помощью Fast Refresh.
  • До 45,8% быстрее начальная компиляция маршрута без кэширования (в Turbopack пока нет дискового кэширования).

Подробнее о Turbopack Dev вы можете узнать из нашей новой статьи в блоге.

Индикатор статического маршрута

Next.js теперь отображает индикатор статических маршрутов во время разработки, чтобы помочь вам определить, какие маршруты являются статическими или динамическими. Эта визуальная подсказка облегчает оптимизацию производительности за счет понимания того, как отображаются ваши страницы.

static route indicator

Вы также можете использовать вывод следующей сборки для просмотра стратегии рендеринга для всех маршрутов.

Это обновление является частью наших постоянных усилий по улучшению наблюдаемости в Next.js, облегчая разработчикам мониторинг, отладку и оптимизацию их приложений. Мы также работаем над специальными инструментами для разработчиков, подробности о которых будут представлены в ближайшее время.

Узнайте больше об индикаторе статических маршрутов, который можно отключить.

Выполнение кода после ответа с помощью unstable_after (Экспериментально)

При обработке пользовательского запроса сервер обычно выполняет задачи, непосредственно связанные с вычислением ответа. Однако вам может потребоваться выполнение таких задач, как ведение журнала, аналитика и синхронизация с другими внешними системами.

Поскольку эти задачи не связаны напрямую с ответом, пользователь не должен ждать их завершения. Откладывание работы после ответа пользователю представляет собой сложную задачу, поскольку бессерверные функции прекращают вычисления сразу после закрытия ответа.

after() - это новый экспериментальный API, который решает эту проблему, позволяя планировать работу после завершения потоковой передачи ответа, что дает возможность запускать вторичные задачи, не блокируя основной ответ.

Чтобы использовать его, добавьте experimental.after в next.config.js:

const nextConfig = {
  experimental: {
    after: true,
  },
};
 
export default nextConfig;

Затем импортируйте функцию в Server Components, Server Actions, Route Handlers или Middleware.

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

Узнайте больше о unstable_after.

instrumentation.js (Стабильно)

Файл инструментария с API register() позволяет пользователям подключаться к жизненному циклу сервера Next.js для мониторинга производительности, отслеживания источников ошибок и глубокой интеграции с библиотеками наблюдаемости, такими как OpenTelemetry.

Теперь эта функция стабильна, и опция конфигурации experimental.instrumentationHook может быть удалена.

Кроме того, мы совместно с Sentry разработали новый хук onRequestError, который можно использовать для:

  • Захват важного контекста обо всех ошибках, возникающих на сервере, включая:
    • Router: Pages Router или App Router
    • Контекст сервера: Server Component, Server Action, Route Handler, или Middleware
  • Сообщите об ошибках вашему любимому провайдеру наблюдаемости.
export async function onRequestError(err, request, context) {
  await fetch('https://...', {
    method: 'POST',
    body: JSON.stringify({ message: err.message, request, context }),
    headers: { 'Content-Type': 'application/json' },
  });
}
 
export async function register() {
  // инициируйте ваш любимый SDK-провайдер
}

Узнайте больше о функции onRequestError.

Form компонент

Новый компонент Form расширяет элемент HTML form с предварительной выборкой, навигацией на стороне клиента и прогрессивным улучшением.

Он полезен для форм, которые переходят на новую страницу, например, форма поиска, ведущая на страницу результатов.

import Form from 'next/form';
 
export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  );
}

Компонент Form поставляется в комплекте:

  • Предварительная выборка: когда форма находится в поле зрения, макет и загружаемый пользовательский интерфейс предварительно выбираются, что ускоряет навигацию.
  • Навигация на стороне клиента: При отправке формы сохраняются общие макеты и состояние на стороне клиента.
  • Прогрессивное улучшение: Если JavaScript еще не загрузился, форма по-прежнему работает через полностраничную навигацию.

Узнайте больше о компоненте Form.

Поддержка next.config.ts

Next.js теперь поддерживает тип файла TypeScript next.config.ts и предоставляет тип NextConfig для автозаполнения и безопасных для типа опций:

import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  /* config */
};
 
export default nextConfig;

Узнайте больше о поддержке TypeScript в Next.js.

Улучшения для самостоятельного хостинга

При самостоятельном размещении приложений вам может понадобиться больше контроля над директивами Cache-Control.

Одним из распространенных случаев является контроль периода stale-while-revalidate, отправляемого для страниц ISR. Мы реализовали два улучшения:

  • Теперь вы можете настроить значение expireTime в next.config. Ранее это была опция experimental.swrDelta.
  • Обновлено значение по умолчанию до одного года, чтобы большинство CDN могли в полной мере применять семантику stale-while-revalidate, как и предполагалось.

Мы также больше не переопределяем пользовательские значения Cache-Control на наши значения по умолчанию, что позволяет полностью контролировать процесс и обеспечивает совместимость с любыми настройками CDN.

Наконец, мы улучшили оптимизацию изображений при самостоятельном размещении. Ранее мы рекомендовали установить sharp для оптимизации изображений на вашем сервере Next.js. Эта рекомендация иногда не выполнялась. В Next.js 15 вам больше не нужно вручную устанавливать sharp - Next.js будет использовать sharp автоматически при использовании next start или при работе в режиме автономного вывода.

Повышенная безопасность действий на сервере

Server Actions - это функции на стороне сервера, которые могут быть вызваны с клиента. Они определяются путем добавления директивы 'use server' в верхней части файла и экспорта async-функции.

Даже если действие сервера или служебная функция не импортируются в другие части кода, они все равно являются общедоступными конечными точками HTTP. Хотя такое поведение технически правильно, оно может привести к непреднамеренному раскрытию таких функций.

Для повышения безопасности мы ввели следующие усовершенствования:

  • Устранение мертвого кода: Неиспользуемые действия сервера не будут иметь своих идентификаторов в JavaScript-пакете на стороне клиента, что уменьшит размер пакета и повысит производительность.
  • Безопасные идентификаторы действий: Next.js теперь создает не поддающиеся проверке недетерминированные идентификаторы, чтобы клиент мог ссылаться на действие сервера и вызывать его. Эти идентификаторы периодически пересчитываются между сборками для повышения безопасности.
// app/actions.js
'use server';
 
// Это действие  используется в нашем приложении, поэтому Next.js 
// создаст безопасный идентификатор, чтобы клиент мог ссылаться
// и вызывать действие сервера.
export async function updateUserAction(formData) {}
 
// Это действие не используется в нашем приложении, поэтому Next.js
// автоматически удалит этот код во время `next build`
// и не будет создавать публичную конечную точку.
export async function deleteUserAction(formData) {}

Вы все равно должны относиться к действиям сервера как к публичным конечным точкам HTTP. Узнайте больше о защите действий сервера.

Оптимизация комплектации внешних пакетов (Стабильно)

Пакетирование внешних пакетов может улучшить производительность приложения при холодном запуске. В App Router внешние пакеты комплектуются по умолчанию, и вы можете отказаться от конкретных пакетов с помощью нового параметра конфигурации serverExternalPackages.

В Pages Router внешние пакеты не собираются по умолчанию, но вы можете предоставить список пакетов, которые нужно собрать, с помощью существующей опции transpilePackages. При использовании этого параметра конфигурации необходимо указать каждый пакет.

Чтобы унифицировать конфигурацию App и Pages Router, мы вводим новую опцию, bundlePagesRouterDependencies, чтобы соответствовать автоматической комплектации App Router по умолчанию. При необходимости вы можете использовать serverExternalPackages для отказа от конкретных пакетов.

const nextConfig = {
  // Automatically bundle external packages in the Pages Router:
  bundlePagesRouterDependencies: true,
  // Opt specific packages out of bundling for both App and Pages Router:
  serverExternalPackages: ['package-name'],
};
 
export default nextConfig;

Узнайте больше об оптимизации внешних пакетов.

Поддержка ESLint 9

В Next.js 15 также появилась поддержка ESLint 9, после того как 5 октября 2024 года закончится срок службы ESLint 8.

Чтобы обеспечить плавный переход, Next.js сохраняет обратную совместимость, то есть вы можете продолжать использовать ESLint 8 или 9.

Если вы обновитесь до ESLint 9, и мы обнаружим, что вы еще не перешли на новый формат конфигурации, Next.js автоматически применит escape hatch ESLINT_USE_FLAT_CONFIG=false, чтобы облегчить переход.

Кроме того, устаревшие опции, такие как -ext и -ignore-path, будут удалены при выполнении следующего lint. Обратите внимание, что ESLint в конечном итоге запретит эти старые конфигурации в ESLint 10, поэтому мы рекомендуем начать миграцию в ближайшее время.

Более подробную информацию об этих изменениях можно найти в руководстве по миграции.

В рамках этого обновления мы также обновили eslint-plugin-react-hooks до версии 5.0.0, которая вводит новые правила использования React Hooks. Вы можете просмотреть все изменения в журнале изменений по адресу eslint-plugin-react-hooks@5.0.0.

dev и prod улучшения

Компоненты сервера HMR

Во время разработки компоненты сервера выполняются повторно при сохранении. Это означает, что все запросы на получение данных к конечным точкам API или сторонним сервисам также будут вызваны.

Чтобы повысить производительность локальной разработки и сократить потенциальные расходы на платные вызовы API, теперь мы обеспечиваем возможность повторного использования ответов на выборку из предыдущих рендеров при горячей замене модулей (HMR).

Узнайте больше о серверных компонентах HMR Cache.

Ускоренная генерация статики для App Router

Мы оптимизировали генерацию статических изображений, чтобы увеличить время сборки, особенно для страниц с медленными сетевыми запросами.

Раньше в процессе статической оптимизации страницы рендерились дважды - один раз для генерации данных для навигации на стороне клиента, а второй раз для рендеринга HTML при первом посещении страницы. Теперь мы повторно используем первый рендер, исключая второй проход, сокращая рабочую нагрузку и время сборки.

Кроме того, рабочие генераторы статических изображений теперь разделяют кэш выборки между страницами. Если вызов fetch не отказывается от кэширования, его результаты повторно используются другими страницами, обрабатываемыми тем же рабочим. Это сокращает количество запросов на одни и те же данные.

Усовершенствованное управление статической генерацией (экспериментальное)

Мы добавили экспериментальную поддержку для большего контроля над процессом генерации статики для продвинутых случаев использования, которые выиграют от большего контроля.

Мы рекомендуем придерживаться текущих настроек по умолчанию, если у вас нет особых требований, так как эти опции могут привести к повышенному использованию ресурсов и потенциальным ошибкам, связанным с выходом за пределы памяти из-за повышенного параллелизма.

const nextConfig = {
  experimental: {
    // how many times Next.js will retry failed page generation attempts
    // before failing the build
    staticGenerationRetryCount: 1
    // how many pages will be processed per worker
    staticGenerationMaxConcurrency: 8
    // the minimum number of pages before spinning up a new export worker
    staticGenerationMinPagesPerWorker: 25
  },
}
 
export default nextConfig;

Узнайте больше о возможностях генерации статики.