Переход в продакшен

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

Общие рекомендации

Кэширование

Примеры

Кэширование улучшает время отклика и уменьшает количество запросов к внешним сервисам. Next.js автоматически добавляет заголовки кэширования для неизменяемых ресурсов из /_next/static, включая JavaScript, CSS, статические изображения и другие медиафайлы.

Cache-Control: public, max-age=31536000, immutable

Заголовки Cache-Control, установленные в next.config.js, будут перезаписаны в продакшене для обеспечения эффективного кэширования статических ресурсов. Если вам нужно перепроверить кэш страницы, сгенерированной статически, вы можете сделать это, установив параметр revalidate в функции getStaticProps страницы. Если вы используете next/image, вы можете настроить minimumCacheTTL для стандартного загрузчика оптимизации изображений.

Полезно знать: При локальном запуске приложения с next dev ваши заголовки перезаписываются для предотвращения локального кэширования.

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Вы также можете использовать заголовки кэширования внутри getServerSideProps и API-роутов для динамических ответов. Например, используя stale-while-revalidate.

// Это значение считается свежим в течение десяти секунд (s-maxage=10).
// Если запрос повторяется в течение следующих 10 секунд, ранее
// закэшированное значение останется свежим. Если запрос повторяется до 59 секунд,
// закэшированное значение будет устаревшим, но все равно отобразится (stale-while-revalidate=59).
//
// На фоне будет выполнен запрос на перепроверку для обновления кэша
// новым значением. Если вы обновите страницу, вы увидите новое значение.
export async function getServerSideProps({ req, res }) {
  res.setHeader(
    'Cache-Control',
    'public, s-maxage=10, stale-while-revalidate=59'
  )

  return {
    props: {},
  }
}

По умолчанию заголовки Cache-Control устанавливаются по-разному в зависимости от того, как ваша страница получает данные.

  • Если страница использует getServerSideProps или getInitialProps, будет использоваться заголовок Cache-Control по умолчанию, установленный next start, чтобы предотвратить случайное кэширование ответов, которые не могут быть закэшированы. Если вам нужно другое поведение кэширования при использовании getServerSideProps, используйте res.setHeader('Cache-Control', 'предпочитаемое_значение') внутри функции, как показано выше.
  • Если страница использует getStaticProps, у нее будет заголовок Cache-Control со значением s-maxage=REVALIDATE_SECONDS, stale-while-revalidate, или если revalidate не используется, s-maxage=31536000, stale-while-revalidate для максимально возможного времени кэширования.

Полезно знать: Ваш провайдер развертывания должен поддерживать кэширование для динамических ответов. Если вы развертываете приложение самостоятельно, вам нужно добавить эту логику самостоятельно, используя хранилище ключ-значение, такое как Redis. Если вы используете Vercel, Edge Caching работает без дополнительной настройки.

Уменьшение размера JavaScript

Примеры

Чтобы уменьшить объем JavaScript, отправляемого в браузер, вы можете использовать следующие инструменты для анализа содержимого каждого JavaScript-бандла:

  • Import Cost – Отображает размер импортируемого пакета в VSCode.
  • Package Phobia – Показывает стоимость добавления новой dev-зависимости в ваш проект.
  • Bundle Phobia - Анализирует, насколько зависимость может увеличить размеры бандлов.
  • Webpack Bundle Analyzer – Визуализирует размер выходных файлов webpack с интерактивной, масштабируемой картой.
  • bundlejs - Онлайн-инструмент для быстрой сборки и минификации проектов с просмотром сжатых размеров бандлов gzip/brotli, работающий локально в вашем браузере.

Каждый файл в вашей директории pages/ автоматически разделяется на отдельный JavaScript-бандл во время next build. Вы также можете использовать Динамические импорты для ленивой загрузки компонентов и библиотек. Например, вы можете отложить загрузку кода модального окна до момента, когда пользователь нажмет кнопку открытия.

Логирование

Примеры

Поскольку Next.js работает как на клиенте, так и на сервере, поддерживаются несколько форм логирования:

  • console.log в браузере
  • stdout на сервере

Если вам нужен структурированный пакет для логирования, мы рекомендуем Pino. Если вы используете Vercel, есть предустановленные интеграции для логирования, совместимые с Next.js.

Обработка ошибок

Примеры

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

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

Производительность загрузки

Чтобы улучшить производительность загрузки, сначала необходимо определить, что измерять и как это измерять. Core Web Vitals – это хороший отраслевой стандарт, который измеряется с помощью вашего веб-браузера. Если вы не знакомы с метриками Core Web Vitals, ознакомьтесь с этой статьей и определите, какие конкретные метрики будут вашими ориентирами для производительности загрузки. В идеале вы должны измерять производительность загрузки в следующих средах:

  • В лаборатории, используя ваш собственный компьютер или симулятор.
  • В реальных условиях, используя данные от реальных посетителей.
  • Локально, используя тест, который запускается на вашем устройстве.
  • Удаленно, используя тест, который запускается в облаке.

Как только вы сможете измерять производительность загрузки, используйте следующие стратегии для ее постепенного улучшения: применяйте одну стратегию, измеряйте новую производительность и продолжайте настройку, пока не увидите значительных улучшений. Затем можно переходить к следующей стратегии.

  • Используйте регионы кэширования, близкие к регионам, где развернуты ваша база данных или API.
  • Как описано в разделе кэширование, используйте значение stale-while-revalidate, которое не перегрузит ваш бэкенд.
  • Используйте Инкрементальную статическую регенерацию для уменьшения количества запросов к вашему бэкенду.
  • Удалите неиспользуемый JavaScript. Ознакомьтесь с этой статьей, чтобы понять, какие метрики Core Web Vitals зависят от размера бандла, и какие стратегии вы можете использовать для его уменьшения, например:
    • Настройте вашу среду разработки для просмотра стоимости и размеров импортов
    • Найдите альтернативные, более легкие пакеты
    • Динамически загружайте компоненты и зависимости