BackНазад к блогу

Next.js 13.3

В Next.js 13.3 появились динамические Open Graph изображения, расширенный статический экспорт, параллельные маршруты и перехват, поддержка OTEL и многое другое.

Next.js 13.3 добавляет популярные функции, запрошенные сообществом, включая:

Обновитесь сегодня, выполнив:

Terminal
npm i next@latest react@latest react-dom@latest eslint-config-next@latest

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

Хотя мы всё ещё работаем над некоторыми функциями, такими как Mutations, мы не ожидаем, что они повлияют на API других функций App Router. Мы с нетерпением ждём, что вы построите с помощью App Router, и рады вашим отзывам.

File-Based Metadata API

В Next.js 13.2 мы представили новый Metadata API, позволяющий определять метаданные (например, теги title, meta и link внутри HTML-элемента head) путём экспорта объекта Metadata из layout или страницы.

layout.js or page.js
// Статические метаданные
export const metadata = {
  title: 'Home',
};
// Результат:
// <head>
//	 <title>Home</title>
// </head>
 
// Или динамические метаданные
export async function generateMetadata({ params, searchParams }) {
  const product = await getProduct(params.id);
  return { title: product.title };
}
// Результат:
// <head>
//	 <title>My Unique Product</title>
// </head>
 
export default function Page() {}

В дополнение к конфигурационным метаданным, Metadata API теперь поддерживает новые файловые соглашения, позволяя удобно настраивать страницы для улучшения SEO и публикации в интернете:

  • opengraph-image.(jpg|png|svg)
  • twitter-image.(jpg|png|svg)
  • favicon.ico
  • icon.(ico|jpg|png|svg)
  • sitemap.(xml|js|jsx|ts|tsx)
  • robots.(txt|js|jsx|ts|tsx)
  • manifest.(json|js|jsx|ts|tsx)

Например, вы можете использовать файловые метаданные для добавления фавикона вашего приложения и Open Graph изображения для страницы /about:

app
├── favicon.ico
├── layout.js
├── page.js
└── about
    ├── opengraph-image.jpg
    └── page.js

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

// При посещении "/"
<link rel="icon" href="<computedUrl>"/>
 
// При посещении "/about"
<link rel="icon" href="<computedUrl>"/>
<meta property="og:image" content="<computedUrl>" type="<computedType>" ... />

Добавление статических файлов в ваше приложение часто является самым простым подходом, но бывают случаи, когда вам может понадобиться создавать файлы динамически. Для каждого статического файлового соглашения существует соответствующий динамический вариант (.js|.jsx|.ts|.tsx), позволяющий писать код для генерации файла.

Например, хотя вы можете добавить статический файл sitemap.xml, большинство сайтов имеют страницы, которые динамически генерируются с использованием внешнего источника данных. Чтобы создать динамическую карту сайта, вы можете добавить файл sitemap.js, возвращающий массив ваших динамических маршрутов.

app/sitemap.js
export default async function sitemap() {
  const res = await fetch('https://.../posts');
  const allPosts = await res.json();
 
  const posts = allPosts.map((post) => ({
    url: `https://acme.com/blog/${post.slug}`,
    lastModified: post.publishedAt,
  }));
 
  const routes = ['', '/about', '/blog'].map((route) => ({
    url: `https://acme.com${route}`,
    lastModified: new Date().toISOString(),
  }));
 
  return [...routes, ...posts];
}

С конфигурационными и новыми файловыми опциями у вас теперь есть комплексный Metadata API, охватывающий как статические, так и динамические метаданные.

Metadata API доступен в 13.3 для App Router (app). Он не доступен в директории pages. Узнайте больше о файловых метаданных и просмотрите API reference.

Динамическая генерация Open Graph изображений

Шесть месяцев назад мы выпустили @vercel/og и Satori, библиотеки, позволяющие динамически генерировать изображения с использованием JSX, HTML и CSS.

@vercel/og прошёл проверку на Next.js Conf, сгенерировав более 100,000 динамических изображений билетов для каждого участника. Благодаря широкому внедрению среди клиентов Vercel и более 900,000 загрузок с момента релиза, мы рады представить динамически генерируемые изображения для всех приложений Next.js без необходимости во внешнем пакете.

Теперь вы можете импортировать ImageResponse из next/server для генерации изображений:

/app/about/opengraph-image.tsx
import { ImageResponse } from 'next/server';
 
export const size = { width: 1200, height: 600 };
export const alt = 'About Acme';
export const contentType = 'image/png';
export const runtime = 'edge';
 
export default function og() {
  return new ImageResponse();
  // ...
}

ImageResponse естественно интегрируется с другими API Next.js, включая Route Handlers и файловые метаданные. Например, вы можете использовать ImageResponse в файле opengraph-image.tsx для генерации Open Graph и Twitter изображений во время сборки или динамически во время запроса.

Узнайте больше о Image Response API.

Статический экспорт для App Router

App Router Next.js теперь поддерживает полностью статический экспорт.

Вы можете начать со статического сайта или SPA (Single-Page Application), а затем при необходимости перейти к использованию функций Next.js, требующих сервера.

При запуске next build Next.js генерирует HTML-файл для каждого маршрута. Разбивая строгое SPA на отдельные HTML-файлы, Next.js может избежать загрузки ненужного JavaScript-кода на стороне клиента, уменьшая размер бандла и обеспечивая более быструю загрузку страниц.

next.config.js
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: 'export',
};
 
module.exports = nextConfig;

Статический экспорт работает с новыми функциями app router, включая статические Route Handlers, Open Graph изображения и React Server Components.

Например, Server Components будут выполняться во время сборки, аналогично традиционной генерации статических сайтов, рендеря компоненты в статический HTML для начальной загрузки страницы и статический payload для клиентской навигации между маршрутами.

Ранее для использования статического экспорта в директории pages требовалось выполнить next export. Однако с опцией next.config.js next build будет выводить директорию out, когда установлено output: 'export'. Вы можете использовать ту же конфигурацию для app router и директории pages. Это означает, что next export больше не требуется.

С расширенной поддержкой статического экспорта вы будете получать ошибки раньше в процессе разработки (next dev), например, при попытке использовать динамическую функцию, требующую сервера, такую как cookies() или headers().

Узнайте больше о Статическом экспорте.

Параллельные маршруты и перехват

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

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

Параллельные маршруты создаются с использованием именованных "слотов". Слоты определяются с соглашением @folder:

dashboard
├── @user
│   └── page.js
├── @team
│   └── page.js
├── layout.js
└── page.js

Layout в том же сегменте маршрута принимает слоты как пропсы:

app/dashboard/layout.js
export default async function Layout({ children, user, team }) {
  const userType = getCurrentUserType();
 
  return (
    <>
      {userType === 'user' ? user : team}
      {children}
    </>
  );
}

В примере выше слоты параллельных маршрутов @user и @team (явные) рендерятся условно на основе вашей логики. children является неявным слотом маршрута, который не нужно сопоставлять с @folder. Например, dashboard/page.js эквивалентен dashboard/@children/page.js.

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

Перехватывающие маршруты могут быть определены с соглашением (..), аналогично относительным путям ../. Вы также можете использовать соглашение (...) для создания пути относительно директории app.

feed
├── @modal
│   └── (..)photo
│       └── [id]
│           └── page.tsx
├── page.tsx
└── layout.tsx
photo
└── [id]
    └── page.tsx

В примере выше клик по фотографии из профиля пользователя откроет фотографию в модальном окне во время клиентской навигации. Однако обновление или совместное использование страницы загрузит фотографию с её стандартным layout.

Параллельные маршруты и перехват позволяют реализовать модальную маршрутизацию, как в Instagram.

Параллельные маршруты и перехват позволяют реализовать модальную маршрутизацию, как в Instagram.

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

Для дополнительных примеров и поведения см. документацию по Параллельным и Перехватывающим маршрутам.

Другие улучшения

  • Обновления дизайна: Главная страница Next.js и галерея были обновлены новым дизайном.
  • Turbopack: Добавлена поддержка Middleware, всех опций next/font и стриминга с Server Components по мере приближения к бета-версии (см. демо). Мы также исправили дополнительные ошибки, обнаруженные при тестировании на зрелых приложениях Next.js, таких как vercel.com и nextjs.org. Узнайте больше.
  • Fast Refresh для next.config.js: Изменения в next.config.js теперь автоматически перезапускают локальный сервер разработки. Это расширяет автоматическую перезагрузку конфигурационных файлов .env, .env.*, jsconfig.json, tsconfig.json.
  • Доступность: App Router теперь включает объявление маршрута из pages. Эта функция объявляет переходы между маршрутами на стороне клиента для скринридеров и других вспомогательных технологий. Узнайте больше.
  • Статически типизированные ссылки: redirects и rewrites, установленные в next.config.js, теперь учитываются при проверке типов. Узнайте больше.
  • Tailwind CSS для create-next-app: При создании нового проекта с npx create-next-app@latest вы теперь можете опционально выбрать Tailwind CSS или использовать флаг --tailwind, чтобы предварительно настроить ваше приложение с этим стилевым решением.
  • Route Handlers: Использование export default вместо поддерживаемого HTTP-глагола теперь вызывает полезную ошибку с route.ts. Узнайте больше о Route Handlers.
  • Изображения: next/image теперь поддерживает атрибут fetchPriority="high".
  • Метаданные: Предыдущий API для метаданных (head.js), устаревший в 13.2, был удалён. Вместо этого используйте встроенную поддержку SEO через Metadata API.
  • Исключение папок из маршрутизации: Префикс _ для папки исключает её и все дочерние сегменты из маршрутизации. Например, app/_dashboard/page.tsx не будет доступен для маршрутизации.
  • App Router: Мы добавили новый хук useParams для клиентских компонентов, чтобы читать динамические параметры для данного сегмента маршрута. Узнайте больше.
  • Улучшенная загрузка стилей: Next.js теперь реализует Suspensey CSS от React, что исправляет многие проблемы с загрузкой CSS и мерцанием нестилизованного контента, особенно во время навигации.
  • Улучшенная обработка Not Found: В дополнение к перехвату ожидаемых ошибок notFound(), корневой файл app/not-found.js также будет обрабатывать любые URL, не обрабатываемые вашим приложением. Это означает, что пользователи, посещающие URL, не обрабатываемый вашим приложением, увидят UI, экспортированный файлом app/not-found.js. Узнайте больше.
  • Улучшенный кэш клиентского роутера: router.refresh() теперь инвалидирует весь кэш, а параметры поиска теперь являются частью ключа кэша, позволяя навигацию между двумя параметрами поиска (например, /?search=leerob и /?search=tim) корректно восстанавливать контент, зависящий от параметра.

Сообщество

Next.js — это результат совместной работы более 2,600 индивидуальных разработчиков, отраслевых партнёров, таких как Google и Meta, и нашей основной команды в Vercel. С более чем 4.2 миллионами загрузок npm в неделю и 104,000+ звёзд на GitHub, Next.js является одним из самых популярных способов создания веб-приложений.

Присоединяйтесь к сообществу на GitHub Discussions, Reddit и Discord.

Этот релиз стал возможен благодаря:

А также вкладу: @shuding, @huozhi, @sokra, @hanneslund, @JesseKoldewijn, @kaguya3222, @yangshun, @ijjk, @konomae, @Brooooooklyn, @jridgewell, @zlrlyy, @JohnDaly, @abhiyandhakal, @benjie, @johnnyomair, @nk980113, @dirheimerb, @DerTimonius, @DuCanhGH, @padmaia, @stafyniaksacha, @Gladowar, @zek, @jankaifer, @styfle, @balazsorban44, @wbinnssmith, @chibicode, @ForsakenHarmony, @franktronics, @FSaldanha, @Schniz, @raisedadead, @AdamKatzDev, @wyattjoh, @leerob, @meesvandongen, @vladikoff, @feedthejim, @tka5, @pyjun01, @gdborton, @M3kH, @aretrace, @shivanshubisht, @alexkirsz, @agrattan0820, @vinaykulk621, @heyitsuzair, @mrkldshv, @timneutkens, @furkanmavili, @swaminator, @EndangeredMassa, @DevEsteves, @rishabhpoddar, @schehata, @molebox, @dlehmhus, @akshaynox, @sp00ls, @janicklas-ralph, @tomryanx, @kwonoj, @karlhorky, @kdy1, @dante-robinson, @lachlanjc, @ianmacartney, @hotters, @isaackatayev, @insik-han, @jayair, @ivanhofer, @javivelasco, @SukkaW, @visshaljagtap, @imranbarbhuiya, @nivak-monarch, @HarshaVardhanReddyDuvvuru, @ianldgs, @ricardofiorani, @swarnava, и @gustavostz.