diff --git a/apps/docs/content/ru/blog/building-apis-with-nextjs.mdx b/apps/docs/content/ru/blog/building-apis-with-nextjs.mdx new file mode 100644 index 00000000..bd646032 --- /dev/null +++ b/apps/docs/content/ru/blog/building-apis-with-nextjs.mdx @@ -0,0 +1,396 @@ +--- +source-updated-at: 2025-05-29T18:05:49.000Z +translation-updated-at: 2025-06-02T19:42:27.344Z +title: Создание API с помощью Next.js +description: Узнайте, как создавать API с использованием Next.js. +author: + - name: Lee Robinson + image: /static/team/lee.jpg +date: 2025-02-28T14:00:00.507Z +image: >- + https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/building-apis-with-nextjs/twitter-card.png +--- + +В этом руководстве рассказывается, как создавать API с помощью Next.js, включая настройку проекта, работу с App Router и Route Handlers, обработку нескольких HTTP-методов, реализацию динамической маршрутизации, создание переиспользуемой middleware-логики и принятие решений о необходимости выделенного API-слоя. + +* [1\. Начало работы](#1-начало-работы) + * [1.1 Создание Next.js приложения](#11-создание-nextjs-приложения) + * [1.2 App Router против Pages Router](#12-app-router-против-pages-router) +* [2\. Зачем (и когда) создавать API с Next.js](#2-зачем-и-когда-создавать-api-с-nextjs) +* [3\. Создание API с Route Handlers](#3-создание-api-с-route-handlers) + * [3.1 Базовая настройка файлов](#31-базовая-настройка-файлов) + * [3.2 Несколько HTTP-методов в одном файле](#32-несколько-http-методов-в-одном-файле) +* [4\. Работа с Web API](#4-работа-с-web-api) + * [4.1 Прямое использование Request & Response](#41-прямое-использование-request--response) + * [4.2 Параметры запроса](#42-параметры-запроса) + * [4.3 Заголовки и куки](#43-заголовки-и-куки) +* [5\. Динамические маршруты](#5-динамические-маршруты) +* [6\. Использование Next.js в качестве прокси или промежуточного слоя](#6-использование-nextjs-в-качестве-прокси-или-промежуточного-слоя) +* [7\. Создание переиспользуемой "middleware"-логики](#7-создание-переиспользуемой-middleware-логики) +* [8\. Деплой и особенности "SPA Mode"](#8-деплой-и-особенности-spa-mode) + * [8.1 Стандартный деплой на Node.js](#81-стандартный-деплой-на-nodejs) + * [8.2 SPA/Статический экспорт](#82-spaстатический-экспорт) + * [8.3 Деплой API на Vercel](#83-деплой-api-на-vercel) +* [9\. Когда можно не создавать API-эндпоинт](#9-когда-можно-не-создавать-api-эндпоинт) +* [10\. Собираем всё вместе](#10-собираем-всё-вместе) +* [Заключение](#заключение) +* [Часто задаваемые вопросы](#часто-задаваемые-вопросы) + * [А как насчёт Server Actions?](#а-как-насчёт-server-actions) + * [Можно ли использовать TypeScript с Route Handlers?](#можно-ли-использовать-typescript-с-route-handlers) + * [Какие лучшие практики аутентификации?](#какие-лучшие-практики-аутентификации) + +[1\. Начало работы](#1-начало-работы) +----------------------------------------- + +### [1.1 Создание Next.js приложения](#11-создание-nextjs-приложения) + +Если вы начинаете с нуля, создайте новый проект Next.js с помощью: + +```bash filename="Terminal" +npx create-next-app@latest --api +``` + +> **Примечание:** Флаг `--api` автоматически включает пример `route.ts` в папке `app/` вашего нового проекта, демонстрируя создание API-эндпоинта. + +### [1.2 App Router против Pages Router](#12-app-router-против-pages-router) + +* **Pages Router**: Исторически Next.js использовал `pages/api/*` для API. Этот подход опирался на объекты запроса/ответа Node.js и API, похожее на Express. +* **App Router (по умолчанию)**: Представленный в Next.js 13, App Router полностью использует стандартные Web API Request/Response. Вместо `pages/api/*` теперь можно размещать файлы `route.ts` или `route.js` в любом месте директории `app/`. + +> **Почему стоит переключиться?** "Route Handlers" в App Router основаны на [Web Platform Request/Response APIs](https://developer.mozilla.org/en-US/docs/Web/API), а не на специфичных для Node.js API. Это упрощает обучение, уменьшает трение и позволяет повторно использовать знания в разных инструментах. + +[2\. Зачем (и когда) создавать API с Next.js](#2-зачем-и-когда-создавать-api-с-nextjs) +------------------------------------------------------------------------------------------ + +1. **Публичный API для нескольких клиентов** + + * Можно создать публичный API, который будет использоваться вашим Next.js веб-приложением, отдельным мобильным приложением или любым сторонним сервисом. Например, вы можете получать данные из /api/users как в React-сайте, так и в React Native мобильном приложении. +2. **Прокси к существующему бэкенду** + + * Иногда нужно скрыть или объединить внешние [микросервисы](https://vercel.com/blog/how-vercel-adopted-microfrontends) за единым эндпоинтом. Route Handlers в Next.js могут выступать в роли прокси или промежуточного слоя для другого существующего бэкенда. Например, можно перехватывать запросы, обрабатывать аутентификацию, преобразовывать данные и затем передавать запрос вышестоящему API. +3. **Вебхуки и интеграции** + + * Если вы получаете внешние колбэки или вебхуки (например, от Stripe, GitHub, Twilio), их можно обрабатывать с помощью Route Handlers. +4. **Кастомная аутентификация** + + * Если нужны сессии, токены или другая логика аутентификации, можно хранить куки, читать заголовки и отвечать соответствующими данными в API-слое Next.js. + +> **Примечание:** Если вам нужно только серверное получение данных для вашего Next.js приложения (и не требуется делиться этими данными внешне), Server Components может быть достаточно для получения данных непосредственно во время рендеринга — отдельный API-слой не требуется. + +[3\. Создание API с Route Handlers](#3-создание-api-с-route-handlers) +--------------------------------------------------------------------------------- + +### [3.1 Базовая настройка файлов](#31-базовая-настройка-файлов) + +В App Router (`app/`) создайте папку, представляющую ваш маршрут, и внутри неё файл `route.ts`. + +Например, для создания эндпоинта на `/api/users`: + +``` +app +└── api + └── users + └── route.ts +``` + +### [3.2 Несколько HTTP-методов в одном файле](#32-несколько-http-методов-в-одном-файле) + +В отличие от API-маршрутов в Pages Router (где был один экспорт по умолчанию), из одного файла можно экспортировать несколько функций, представляющих разные HTTP-методы. + +```ts filename="app/api/users/route.ts" +export async function GET(request: Request) { + // Например, здесь можно получить данные из БД + const users = [ + { id: 1, name: 'Алиса' }, + { id: 2, name: 'Боб' } + ]; + return new Response(JSON.stringify(users), { + status: 200, + headers: { 'Content-Type': 'application/json' } + }); +} + +export async function POST(request: Request) { + // Разбираем тело запроса + const body = await request.json(); + const { name } = body; + + // Например, вставляем нового пользователя в БД + const newUser = { id: Date.now(), name }; + + return new Response(JSON.stringify(newUser), { + status: 201, + headers: { 'Content-Type': 'application/json' } + }); +} +``` + +Теперь GET-запрос к `/api/users` возвращает список пользователей, а POST-запрос на тот же URL добавляет нового пользователя. + +[4\. Работа с Web API](#4-работа-с-web-api) +----------------------------------------------------- + +### [4.1 Прямое использование Request & Response](#41-прямое-использование-request--response) + +По умолчанию методы Route Handler (`GET`, `POST` и т.д.) получают стандартный объект [Request](https://developer.mozilla.org/docs/Web/API/Request), и вы должны возвращать стандартный объект [Response](https://developer.mozilla.org/docs/Web/API/Response). + +### [4.2 Параметры запроса](#42-параметры-запроса) + +```ts filename="app/api/search/route.ts" +import { NextRequest } from 'next/server'; + +export function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const query = searchParams.get('query'); // например, `/api/search?query=hello` + + return new Response( + JSON.stringify({ result: `Вы искали: ${query}` }), + { + headers: { 'Content-Type': 'application/json' }, + }, + ); +} +``` + +### [4.3 Заголовки и куки](#43-заголовки-и-куки) + +```ts filename="app/api/auth/route.ts" +import { NextRequest } from 'next/server'; +import { cookies, headers } from 'next/headers'; + +export async function GET(request: NextRequest) { + // 1. Использование помощников из 'next/headers' + const cookieStore = await cookies(); + const token = cookieStore.get('token'); + + const headersList = await headers(); + const referer = headersList.get('referer'); + + // 2. Использование стандартных Web API + const userAgent = request.headers.get('user-agent'); + + return new Response(JSON.stringify({ token, referer, userAgent }), { + headers: { 'Content-Type': 'application/json' }, + }); +} +``` + +Функции `cookies()` и `headers()` могут быть полезны, если вы планируете повторно использовать общую логику в другом серверном коде Next.js. Обратите внимание, что Next.js также предоставляет `NextRequest` и `NextResponse`, которые расширяют базовые Web API. + +[5\. Динамические маршруты](#5-динамические-маршруты) +--------------------------------------- + +Для создания динамических путей (например, `/api/users/:id`) используйте **Dynamic Segments** в структуре папок: + +``` +app +└── api + └── users + └── [id] + └── route.ts +``` + +Этот файл соответствует URL типа `/api/users/123`, где `123` захватывается как параметр. + +```ts filename="app/api/users/[id]/route.ts" +import { NextRequest } from 'next/server'; + +export async function GET( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + const id = (await params).id; + // Например, запрос пользователя с ID `id` из БД + return new Response(JSON.stringify({ id, name: `Пользователь ${id}` }), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); +} + +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + const id = (await params).id; + // Например, удаление пользователя с ID `id` из БД + return new Response(null, { status: 204 }); +} +``` + +Здесь `params.id` даёт вам динамический сегмент. + +[6\. Использование Next.js в качестве прокси или промежуточного слоя](#6-использование-nextjs-в-качестве-прокси-или-промежуточного-слоя) +-------------------------------------------------------------------------------------------------- + +Распространённый сценарий — **проксирование** существующего бэкенд-сервиса. Можно аутентифицировать запросы, вести логирование или преобразовывать данные перед отправкой на удалённый сервер или бэкенд: + +```ts filename="app/api/external/route.ts" +import { NextRequest } from 'next/server'; + +export async function GET(request: NextRequest) { + const response = await fetch('https://example.com/api/data', { + // Опционально: передача заголовков, добавление токенов аутентификации и т.д. + headers: { Authorization: `Bearer ${process.env.API_TOKEN}` }, + }); + + // Преобразование или передача ответа + const data = await response.json(); + const transformed = { ...data, source: 'проксировано-через-nextjs' }; + + return new Response(JSON.stringify(transformed), { + headers: { 'Content-Type': 'application/json' }, + }); +} +``` + +Теперь клиентам нужно только вызывать `/api/external`, а Next.js обработает остальное. Это иногда называют "Backend for Frontend" или BFF. + +[7\. Создание переиспользуемой "middleware"-логики](#7-создание-переиспользуемой-middleware-логики) +----------------------------------------------------------------------------- + +Если нужно применить одну и ту же логику (например, проверки аутентификации, логирование) к нескольким Route Handlers, можно создать переиспользуемые функции, оборачивающие ваши обработчики: + +```ts filename="lib/with-auth.ts" +import { NextRequest } from 'next/server'; + +type Handler = (req: NextRequest, context?: any) => Promise; + +export function withAuth(handler: Handler): Handler { + return async (req, context) => { + const token = req.cookies.get('token')?.value; + if (!token) { + return new Response(JSON.stringify({ error: 'Не авторизован' }), { + status: 401, + headers: { 'Content-Type': 'application/json' }, + }); + } + + // Если аутентификация прошла, вызываем оригинальный обработчик + return handler(req, context); + }; +} +``` + +Затем в вашем Route Handler: + +```ts filename="app/api/secret/route.ts" +import { NextRequest } from 'next/server'; +import { withAuth } from '@/lib/with-auth'; + +async function secretGET(request: NextRequest) { + return new Response(JSON.stringify({ secret: 'Здесь водятся драконы' }), { + headers: { 'Content-Type': 'application/json' }, + }); +} + +export const GET = withAuth(secretGET); +``` + +[8\. Деплой и особенности "SPA Mode"](#8-деплой-и-особенности-spa-mode) +----------------------------------------------------------------------------------------- + +### [8.1 Стандартный деплой на Node.js](#81-стандартный-деплой-на-nodejs) + +Стандартный деплой Next.js сервера с использованием `next start` позволяет использовать такие функции, как Route Handlers, Server Components, Middleware и другие — с возможностью работы с динамической информацией во время запроса. + +Дополнительная конфигурация не требуется. Подробнее см. в разделе [Деплой](/docs/app/building-your-application/deploying). + +### [8.2 SPA/Статический экспорт](#82-spaстатический-экспорт) + +Next.js также поддерживает экспорт всего сайта как [статического Single-Page Application (SPA)](/docs/app/building-your-application/upgrading/single-page-applications). + +Это можно включить, установив: + +```ts filename="next.config.ts" +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + output: 'export', +}; + +export default nextConfig; +``` + +В **режиме статического экспорта** Next.js генерирует чисто статические HTML, CSS и JS. **Нельзя выполнять серверный код** (например, API-эндпоинты). Если API всё ещё нужен, его придётся размещать отдельно (например, на отдельном Node.js сервере). + +> **Примечание:** +> +> * **GET Route Handlers** [могут быть статически экспортированы](/docs/app/building-your-application/deploying/static-exports#route-handlers), если они не зависят от динамических данных запроса. Они становятся статическими файлами в папке `out`. +> * **Все остальные серверные функции** (динамические запросы, перезапись куки и т.д.) **не поддерживаются** в чистом SPA экспорте. + +### [8.3 Развертывание API на Vercel](#83-deploying-apis-on-vercel) + +Если вы развертываете свое Next.js-приложение на Vercel, у нас есть [руководство по развертыванию API](https://vercel.com/guides/hosting-backend-apis). Оно включает другие функции Vercel, такие как [программное ограничение частоты запросов (rate-limiting)](https://vercel.com/docs/security/vercel-waf/rate-limiting-sdk) через Vercel Firewall. Vercel также предлагает [Cron Jobs](https://vercel.com/docs/cron-jobs/manage-cron-jobs), которые часто требуются при работе с API. + +[9\. Когда можно не создавать конечную точку API](#9-when-to-skip-creating-an-api-endpoint) +------------------------------------------------------------------------------------- + +С **React Server Components** в App Router вы можете получать данные напрямую на сервере, не создавая публичную конечную точку: + +```tsx filename="app/users/page.tsx" +// (Server Component) +export default async function UsersPage() { + // Этот fetch выполняется на сервере (клиентский код здесь не нужен) + const res = await fetch('https://api.example.com/users'); + const data = await res.json(); + + return ( +
+

Пользователи

+ +
+ ); +} +``` + +Если ваши данные используются только внутри вашего Next.js-приложения, вам может вообще не понадобиться публичное API. + +[10\. Собираем все вместе](#10-putting-it-all-together) +----------------------------------------------------------- + +1. **Создайте новый проект Next.js**: `npx create-next-app@latest --api`. +2. **Добавьте Route Handlers** в директорию `app/` (например, `app/api/users/route.ts`). +3. **Экспортируйте HTTP-методы** (`GET`, `POST`, `PUT`, `DELETE` и т.д.) в том же файле. +4. **Используйте стандартные веб-API** для работы с объектом `Request` и возврата `Response`. +5. **Создайте публичное API**, если вам нужно, чтобы другие клиенты использовали ваши данные, или для проксирования серверного сервиса. +6. **Получайте данные** из новых API-маршрутов на клиенте (например, внутри Client Component или с помощью `fetch('/api/...')`). +7. Или **вообще не создавайте API**, если Server Component может просто получать данные. +8. **Добавьте общий шаблон "middleware"** (например, `withAuth()`) для аутентификации или другой повторяющейся логики. +9. **Разверните** в среде с поддержкой Node.js для серверных функций или **экспортируйте** статически, если вам нужно только статическое SPA. + +[Заключение](#conclusion) +------------------------- + +Использование **App Router** и **Route Handlers** в Next.js дает вам гибкий, современный способ создания API, напрямую использующих **Web Platform**. Вы можете: + +* **Создать полноценное публичное API** для использования веб-, мобильными или сторонними клиентами. +* **Проксировать** и настраивать вызовы существующих внешних сервисов. +* **Реализовать** повторно используемый слой "middleware" для аутентификации, логирования или любой повторяющейся логики. +* **Динамически маршрутизировать** запросы с помощью структуры папок `[id]`. + +[Часто задаваемые вопросы](#frequently-asked-questions) +--------------------------------------------------------- + +### [А как насчет Server Actions?](#what-about-server-actions) + +Можно рассматривать [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) как автоматически генерируемые `POST` API-маршруты, которые можно вызывать с клиента. + +Они предназначены для операций изменения данных, таких как создание, обновление или удаление. Вы вызываете Server Action как обычную JavaScript-функцию, вместо явного `fetch` к определенному API-маршруту. + +Хотя сетевой запрос все равно происходит, вам не нужно управлять им явно. URL-путь генерируется автоматически и [шифруется](/docs/app/building-your-application/data-fetching/server-actions-and-mutations#security), поэтому вы не можете вручную обратиться к маршруту типа `/api/users` в браузере. + +Если вы планируете использовать Server Actions _и_ предоставлять публичное API, мы рекомендуем вынести основную логику в [Data Access Layer](/blog/security-nextjs-server-components-actions) и вызывать одну и ту же логику как из Server Action, так и из API-маршрута. + +### [Можно ли использовать TypeScript с Route Handlers?](#can-i-use-typescript-with-route-handlers) + +Да, вы можете использовать TypeScript с Route Handlers. Например, определяя типы `Request` и `Response` в вашем файле `route`. + +Подробнее о [TypeScript в Next.js](/docs/app/api-reference/config/typescript). + +### [Какие лучшие практики для аутентификации?](#what-are-the-best-practices-for-authentication) + +Узнайте больше в нашей [документации по аутентификации](/docs/app/building-your-application/authentication). diff --git a/apps/docs/content/ru/blog/composable-caching.mdx b/apps/docs/content/ru/blog/composable-caching.mdx new file mode 100644 index 00000000..6bc349d8 --- /dev/null +++ b/apps/docs/content/ru/blog/composable-caching.mdx @@ -0,0 +1,202 @@ +--- +source-updated-at: 2025-05-29T18:05:49.000Z +translation-updated-at: 2025-06-02T19:40:33.803Z +title: Компонуемое кэширование в Next.js +description: Узнайте больше о дизайне API и преимуществах директивы 'use cache' +author: + - name: Lee Robinson + image: /static/team/lee.jpg +date: 2025-01-03T14:00:00.507Z +image: >- + https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/composable-caching/twitter-card.png +--- + +Мы работаем над простой и мощной моделью кэширования для Next.js. В предыдущей статье мы рассказывали о [нашем пути работы с кэшированием](/blog/our-journey-with-caching) и о том, как мы пришли к директиве `'use cache'`. + +Эта статья расскажет о дизайне API и преимуществах `'use cache'`. + +[Что такое `'use cache'`?](#что-такое-use-cache) +-------------------------------------------- + +`'use cache'` ускоряет ваше приложение, кэшируя данные или компоненты по мере необходимости. + +Это JavaScript-директива — строковый литерал, который вы добавляете в код — она сигнализирует компилятору Next.js о переходе в другую "границу". Например, с сервера на клиент. + +Это похоже на директивы React, такие как `'use client'` и `'use server'`. Директивы — это инструкции компилятору, определяющие, где должен выполняться код, позволяя фреймворку оптимизировать и оркестрировать отдельные части за вас. + +[Как это работает?](#как-это-работает) +-------------------------------------- + +Начнём с простого примера: + +``` +async function getUser(id) { + 'use cache'; + let res = await fetch(`https://api.vercel.app/user/${id}`); + return res.json(); +} +``` + +Под капотом Next.js преобразует этот код в серверную функцию благодаря директиве `'use cache'`. Во время компиляции "зависимости" этой записи кэша определяются и используются как часть ключа кэширования. + +Например, `id` становится частью ключа кэша. Если мы вызовем `getUser(1)` несколько раз, мы вернём мемоизированный результат из кэшированной серверной функции. Изменение этого значения создаст новую запись в кэше. + +Рассмотрим пример использования кэшированной функции в серверном компоненте с [замыканием](https://v0.dev/chat/5kD47RIecQK?b=b_rCP4CvfbFFW). + +``` +function Profile({ id }) { + async function getNotifications(index, limit) { + 'use cache'; + return await db + .select() + .from(notifications) + .limit(limit) + .offset(index) + .where(eq(notifications.userId, id)); + } + + return ; +} +``` + +Этот пример сложнее. Можете ли вы определить все зависимости, которые должны быть частью ключа кэша? + +Аргументы `index` и `limit` очевидны — если эти значения изменятся, мы выберем другой срез уведомлений. Но что насчёт `id` пользователя? Его значение приходит из родительского компонента. + +Компилятор понимает, что `getNotifications` также зависит от `id`, и его значение автоматически включается в ключ кэша. Это предотвращает целый класс проблем кэширования из-за некорректных или пропущенных зависимостей в ключе. + +[Почему бы не использовать функцию кэширования?](#почему-бы-не-использовать-функцию-кэширования) +-------------------------------------------------------------- + +Вернёмся к предыдущему примеру. Могли бы мы использовать функцию `cache()` вместо директивы? + +``` +function Profile({ id }) { + async function getNotifications(index, limit) { + return await cache(async () => { + return await db + .select() + .from(notifications) + .limit(limit) + .offset(index) + // Ой! Где нам включить id в ключ кэша? + .where(eq(notifications.userId, id)); + }); + } + + return ; +} +``` + +Функция `cache()` не сможет заглянуть в замыкание и увидеть, что значение `id` должно быть частью ключа кэша. Вам придётся вручную указывать, что `id` является частью ключа. Если вы забудете это сделать или сделаете неправильно, это может привести к коллизиям кэша или устаревшим данным. + +Замыкания могут захватывать различные локальные переменные. Наивный подход может случайно включить (или исключить) переменные, которые вы не планировали. Это может привести к кэшированию не тех данных или даже к утечке конфиденциальной информации в ключ кэша. + +`'use cache'` даёт компилятору достаточно контекста для безопасной работы с замыканиями и корректного формирования ключей кэша. Решение только на уровне выполнения, такое как `cache()`, потребует ручной работы — и легко ошибиться. В отличие от этого, директива может быть статически проанализирована для надёжной обработки всех зависимостей под капотом. + +[Как обрабатываются несериализуемые входные значения?](#как-обрабатываются-несериализуемые-входные-значения) +-------------------------------------------------------------------------------------------- + +У нас есть два типа входных значений для кэширования: + +* **Сериализуемые**: Здесь "сериализуемые" означает, что входные данные могут быть преобразованы в стабильный строковый формат _без_ потери смысла. Хотя многие сначала думают о `JSON.stringify`, мы фактически используем сериализацию React (например, через Server Components) для обработки более широкого диапазона входных данных — включая промисы, циклические структуры данных и другие сложные объекты. Это выходит за рамки возможностей обычного JSON. +* **Несериализуемые**: Эти входные данные не являются частью ключа кэша. При попытке кэшировать эти значения мы возвращаем серверную "ссылку". Затем Next.js использует эту ссылку для восстановления исходного значения во время выполнения. + +Допустим, мы не забыли включить `id` в ключ кэша: + +``` +await cache(async () => { + return await db + .select() + .from(notifications) + .limit(limit) + .offset(index) + .where(eq(notifications.userId, id)); +}, [id, index, limit]); +``` + +Это работает, если входные значения сериализуемы. Но если бы `id` был React-элементом или более сложным значением, нам пришлось бы вручную сериализовать ключи. Рассмотрим серверный компонент, который получает текущего пользователя на основе пропса `id`: + +``` +async function Profile({ id, children }) { + 'use cache'; + const user = await getUser(id); + + return ( + <> +

{user.name}

+ {/* Изменение children не нарушает кэш... почему? */} + {children} + + ); +} +``` + +Разберём, как это работает: + +1. Во время компиляции Next.js видит директиву `'use cache'` и преобразует код для создания специальной серверной функции с поддержкой кэширования. Кэширование не происходит во время компиляции, но Next.js настраивает механизм, необходимый для кэширования во время выполнения. +2. Когда ваш код вызывает "функцию кэша", Next.js сериализует аргументы функции. Всё, что не может быть сериализовано напрямую, например JSX, заменяется "ссылкой"-заполнителем. +3. Next.js проверяет, существует ли кэшированный результат для данных сериализованных аргументов. Если результат не найден, функция вычисляет новое значение для кэширования. +4. После завершения работы функции возвращаемое значение сериализуется. Несериализуемые части возвращаемого значения преобразуются обратно в ссылки. +5. Код, вызвавший функцию кэша, десериализует вывод и вычисляет ссылки. Это позволяет Next.js заменить ссылки их фактическими объектами или значениями, что означает, что несериализуемые входные данные, такие как `children`, могут сохранить свои исходные, некэшированные значения. + +Это означает, что мы можем безопасно кэшировать _только_ компонент ``, а не дочерние элементы. При последующих рендерах `getUser()` не вызывается снова. Значение `children` может быть динамическим или отдельно кэшированным элементом с другим сроком жизни кэша. Это и есть компонуемое кэширование. + +[Это кажется знакомым...](#это-кажется-знакомым) +-------------------------------------------- + +Если вы думаете: "Это похоже на ту же модель композиции сервера и клиента" — вы абсолютно правы. Это иногда называют паттерном "пончик": + +* **Внешняя** часть пончика — это серверный компонент, который обрабатывает получение данных или сложную логику. +* **Дырка** в середине — это дочерний компонент, который может иметь некоторую интерактивность. + +```tsx filename="app/page.tsx" +export default function Page() { + return ( + + {/* Создаём отверстие к клиенту */} + + + ); +} +``` + +`'use cache'` работает так же. Пончик — это кэшированное значение внешнего компонента, а дырка — это ссылки, которые заполняются во время выполнения. Вот почему изменение `children` не аннулирует весь кэшированный вывод. Дочерние элементы — это просто ссылки, которые заполняются позже. + +[А как насчёт тегирования и инвалидации?](#а-как-насчёт-тегирования-и-инвалидации) +---------------------------------------------------------------------------- + +Вы можете определить срок жизни кэша с помощью различных [профилей](/docs/app/api-reference/functions/cacheLife). Мы включаем набор профилей по умолчанию, но вы можете определить свои собственные значения, если это необходимо. + +``` +async function getUser(id) { + 'use cache'; + cacheLife('hours'); + let res = await fetch(`https://api.vercel.app/user/${id}`); + return res.json(); +} +``` + +Чтобы аннулировать конкретную запись кэша, вы можете [пометить кэш](/docs/app/api-reference/functions/cacheTag) и затем вызвать `revalidateTag()`. Одна мощная особенность — вы можете пометить кэш _после_ получения данных (например, из CMS): + +``` +async function getPost(postId) { + 'use cache'; + let res = await fetch(`https://api.vercel.app/blog/${postId}`); + let data = await res.json(); + cacheTag(postId, data.authorId); + return data; +} +``` + +[Просто и мощно](#просто-и-мощно) +------------------------------------------- + +Наша цель с `'use cache'` — сделать создание логики кэширования простым _и_ мощным. + +* **Простота:** Вы можете создавать записи кэша с локальным рассуждением. Вам не нужно беспокоиться о глобальных побочных эффектах, таких как забытые записи ключей кэша или непреднамеренные изменения других частей вашей кодовой базы. +* **Мощь:** Вы можете кэшировать больше, чем просто статически анализируемый код. Например, значения, которые могут изменяться во время выполнения, но вы всё равно хотите кэшировать результат после его вычисления. + +`'use cache'` всё ещё является **экспериментальной** функцией в Next.js. Мы будем рады вашему раннему отзыву, когда вы протестируете её. + +[Узнайте больше в документации](/docs/app/api-reference/directives/use-cache). \ No newline at end of file diff --git a/apps/docs/content/ru/blog/create-next-app.mdx b/apps/docs/content/ru/blog/create-next-app.mdx new file mode 100644 index 00000000..e8f33404 --- /dev/null +++ b/apps/docs/content/ru/blog/create-next-app.mdx @@ -0,0 +1,39 @@ +--- +source-updated-at: 2025-05-29T18:05:49.000Z +translation-updated-at: 2025-06-02T19:39:06.699Z +title: Представляем Create Next App +description: >- + Сегодня мы рады представить новый Create Next App. Create Next App позволяет + настроить современное React-приложение на базе Next.js всего одной командой. +author: + - name: Joe Haddad + image: /static/team/timer.jpg + - name: Tim Neutkens + image: /static/team/tim.jpg +date: 2019-10-09T15:02:30.543Z +image: >- + https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/create-next-app/twitter-card.png +--- + +Сегодня мы рады представить новый Create Next App. + +Create Next App позволяет настроить современное React-приложение на базе Next.js всего одной командой. + +Чтобы начать, просто выполните: + +```bash filename="Terminal" +npx create-next-app +``` + +Create Next App был полностью переработан, чтобы обеспечить наилучший опыт разработчика: + +* **Интерактивный интерфейс**: Запуск `npx create-next-app` (без аргументов) теперь запускает интерактивный интерфейс, который проведёт вас через процесс настройки проекта. +* **Нет зависимостей**: Инициализация проекта теперь занимает всего **одну секунду**. Create Next App не имеет зависимостей и занимает всего **604 КБ**. До оптимизации предыдущая версия весила **5.38 МБ**. Это сокращение более чем на **4.7 МБ**! +* **Поддержка офлайн-режима**: Create Next App автоматически определит, если вы находитесь офлайн, и создаст проект, используя локальный кеш пакетов. +* **Новый шаблон проекта**: Create Next App использует новый шаблон проекта, разработанный для современных приложений на Next.js. Поскольку Create Next App теперь поддерживается вместе с самим Next.js, этот шаблон всегда будет актуален с последней версией Next.js! +* **Поддержка примеров**: Create Next App может создать ваше приложение на основе примеров из [коллекции примеров Next.js](https://github.com/vercel/next.js/tree/canary/examples) (например, `npx create-next-app --example api-routes`). +* **Протестировано**: Пакет является частью монорепозитория Next.js и тестируется с использованием того же набора интеграционных тестов, что и сам Next.js, что гарантирует его корректную работу с каждым релизом. + +Ранее Create Next App был [проектом, поддерживаемым сообществом](https://open.segment.com/create-next-app/), однако мы посчитали важным курировать первое впечатление от Next.js. Особенно учитывая, что мы рекомендуем его в [коллекции примеров Next.js](https://github.com/vercel/next.js/tree/canary/examples). + +Мы сотрудничали с [Segment](https://segment.com/) для передачи прав на пакет и очень благодарны за их предыдущее управление, особенно [Fouad Matin](https://twitter.com/fouadmatin). \ No newline at end of file diff --git a/apps/docs/content/ru/blog/incremental-adoption.mdx b/apps/docs/content/ru/blog/incremental-adoption.mdx new file mode 100644 index 00000000..2e933299 --- /dev/null +++ b/apps/docs/content/ru/blog/incremental-adoption.mdx @@ -0,0 +1,109 @@ +--- +source-updated-at: 2025-05-29T18:05:49.000Z +translation-updated-at: 2025-06-02T19:40:01.403Z +title: Постепенное внедрение Next.js +description: >- + Изучите различные стратегии постепенного внедрения Next.js в ваш рабочий процесс разработки. +author: + - name: Lee Robinson + image: /static/team/lee.jpg +date: 2020-11-18T14:00:00.507Z +image: >- + https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/incremental-adoption/twitter-card.png +--- + +[Next.js](https://nextjs.org/) разработан для постепенного внедрения. С Next.js вы можете продолжать использовать существующий код и добавлять столько React, сколько вам нужно. Начиная с малого и постепенно добавляя новые страницы, вы можете избежать полного переписывания кода и не срывать работу над функциями. + +Многие компании нуждаются в модернизации своего технологического стека для снижения затрат, повышения производительности разработчиков и обеспечения лучшего опыта для клиентов. Компонентно-ориентированная разработка значительно улучшила скорость развертывания и повторное использование кода в современных проектах. + +С более чем [8 миллионами загрузок в месяц](https://www.npmtrends.com/react), React является ведущим выбором для компонентно-ориентированной разработки. Next.js, фреймворк React для продакшена, позволяет постепенно внедрять React. + +[Мотивация](#motivation) +------------------------- + +В мире, где мобильные устройства играют все большую роль, улучшение и отслеживание [Core Web Vitals](/analytics) критически важно для успеха. Ваши клиенты, вероятно, распределены по всему миру с разной скоростью интернета. Каждая дополнительная секунда (или миллисекунда) ожидания загрузки страницы или выполнения действия может стать разницей между продажей, показом или конверсией. + +Если вы модернизируете свой технологический стек, вы можете столкнуться с такими проблемами, как: + +* Ваше приложение содержит годы устаревшего кода, который сложно понять, и полное переписывание заняло бы годы (и миллионы долларов). +* Время загрузки страниц продолжает расти по мере увеличения размера и сложности приложения. Простые маркетинговые страницы загружаются так же медленно, как и самые сложные. +* Вы пытаетесь масштабировать команду разработчиков, но сталкиваетесь с проблемами при добавлении новых разработчиков в существующую кодовую базу. +* У вас устаревшие процессы CI/CD и DevOps, которые снижают производительность разработчиков и затрудняют безопасное и надежное внедрение изменений. +* Ваше приложение не адаптировано для мобильных устройств, и невозможно обновить глобальные стили страницы, не нарушив другие части приложения. + +Вы знаете, что нужно что-то делать, но может быть сложно понять, [с чего начать](https://www.psychologytoday.com/us/blog/mindfully-present-fully-alive/201804/the-only-way-eat-elephant). Постепенно внедряя Next.js, вы можете начать решать вышеперечисленные проблемы и преобразовать свое приложение. Давайте обсудим несколько стратегий внедрения Next.js в существующий технологический стек. + +[Стратегии](#strategies) +------------------------- + +### [Подпуть (Subpath)](#subpath) + +Первая стратегия заключается в настройке вашего сервера или прокси таким образом, чтобы все содержимое определенного подпути указывало на приложение Next.js. Например, ваш существующий веб-сайт может находиться на `example.com`, а вы можете настроить прокси так, чтобы `example.com/store` обслуживал интернет-магазин на Next.js. + +Используя [`basePath`](/docs/pages/api-reference/next-config-js/basePath), вы можете настроить ресурсы и ссылки вашего приложения Next.js для автоматической работы с новым подпутем `/store`. Поскольку каждая страница в Next.js является [автономным маршрутом](/docs/pages/building-your-application/routing), страницы, такие как `pages/products.js`, будут маршрутизироваться на `example.com/store/products` в вашем приложении. + +```js filename="next.config.js" +module.exports = { + basePath: '/store', +}; +``` + +Чтобы узнать больше о `basePath`, ознакомьтесь с нашей [документацией](/docs/pages/api-reference/next-config-js/basePath). + +(**Примечание:** Эта функция была добавлена в Next.js 9.5 и выше. Если вы используете более старые версии Next.js, обновите их перед использованием.) + +### [Перезаписи (Rewrites)](#rewrites) + +Вторая стратегия заключается в создании нового приложения Next.js, которое указывает на корневой URL вашего домена. Затем вы можете использовать [`rewrites`](/docs/pages/api-reference/next-config-js/rewrites) в `next.config.js`, чтобы некоторые подпути перенаправлялись на ваше существующее приложение. + +Например, предположим, что вы создали приложение Next.js для обслуживания с `example.com` со следующим `next.config.js`. Теперь запросы к страницам, которые вы добавили в это приложение Next.js (например, `/about`, если вы добавили `pages/about.js`), будут обрабатываться Next.js, а запросы к любым другим маршрутам (например, `/dashboard`) будут перенаправляться на `proxy.example.com`. + +```js filename="next.config.js" +module.exports = { + async rewrites() { + return [ + // нам нужно определить перезапись без изменений, чтобы проверить + // все страницы/статические файлы перед попыткой перенаправления + { + source: '/:path*', + destination: '/:path*', + }, + { + source: '/:path*', + destination: `https://proxy.example.com/:path*`, + }, + ]; + }, +}; +``` + +Чтобы узнать больше о перезаписях, ознакомьтесь с нашей [документацией](/docs/pages/api-reference/next-config-js/rewrites). + +### [Микрофронтенды с монорепозиториями и поддоменами](#micro-frontends-with-monorepos-and-subdomains) + +Next.js и [Vercel](https://vercel.com) упрощают внедрение [микрофронтендов](https://martinfowler.com/articles/micro-frontends.html) и развертывание в виде [монорепозитория](https://vercel.com/blog/monorepos). Это позволяет использовать [поддомены](https://ru.wikipedia.org/wiki/Поддомен) для постепенного внедрения новых приложений. Некоторые преимущества микрофронтендов: + +* Меньшие, более связные и поддерживаемые кодовые базы. +* Более масштабируемые организации с развязанными, автономными командами. +* Возможность обновлять, изменять или даже переписывать части фронтенда более постепенно. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/incremental-adoption/light-arch.png) + +> Архитектура монорепозитория, развернутого на Vercel. + +После настройки монорепозитория отправляйте изменения в ваш Git-репозиторий как обычно, и вы увидите, что коммиты развертываются в проектах Vercel, которые вы подключили. Попрощайтесь с устаревшими процессами CI/CD. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/incremental-adoption/dark-comment.png) + +> Пример URL-адресов развертывания, предоставляемых интеграцией с Git. + +[Заключение](#conclusion) +------------------------- + +Next.js разработан для постепенного внедрения в ваш существующий технологический стек. Платформа Vercel делает этот процесс совместным, предоставляя предпросмотры развертывания для каждого изменения кода благодаря бесшовной интеграции с GitHub, GitLab и Bitbucket. + +* Мгновенно просматривайте изменения локально с помощью [Fast Refresh](/docs/architecture/fast-refresh), повышая производительность разработчиков. +* Отправляйте изменения для создания [Branch Preview](https://vercel.com/github), оптимизированного для совместной работы с заинтересованными сторонами. +* Развертывайте в продакшене с [Vercel](https://vercel.com), просто объединяя PR. Никаких сложных DevOps. + +Чтобы узнать больше, прочитайте о [подпутях](/docs/pages/api-reference/next-config-js/basePath) и [перезаписях](/docs/pages/api-reference/next-config-js/rewrites) или [разверните пример с микрофронтендами](https://vercel.com/import/project?template=https://github.com/vercel/next.js/tree/canary/examples/with-zones). \ No newline at end of file diff --git a/apps/docs/content/ru/blog/june-2023-update.mdx b/apps/docs/content/ru/blog/june-2023-update.mdx new file mode 100644 index 00000000..34248267 --- /dev/null +++ b/apps/docs/content/ru/blog/june-2023-update.mdx @@ -0,0 +1,147 @@ +--- +source-updated-at: 2025-05-29T18:05:49.000Z +translation-updated-at: 2025-06-02T19:40:43.973Z +title: Обновление App Router в Next.js +description: >- + Команда Next.js сосредоточена на производительности, стабильности и удобстве разработчиков в предстоящие месяцы. +author: + - name: Delba de Oliveira + image: /static/team/delba.jpg + - name: Lee Robinson + image: /static/team/lee.jpg +date: 2023-06-22T14:00:00.507Z +image: >- + https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/june-2023-update/twitter-card.png +--- + +App Router представляет собой новую основу для будущего Next.js, но мы признаем, что есть возможности улучшить этот опыт. Мы хотели бы поделиться обновлением о наших текущих приоритетах. + +В предстоящих релизах Next.js мы сосредоточены на следующих направлениях: + +* **Улучшение производительности** +* **Повышение стабильности** +* **Развитие образовательных материалов для разработчиков** + +[App Router](#the-app-router) +---------------------------- + +Для начала полезно дать некоторый контекст о том, как был спроектирован App Router. + +### [Выход за пределы Pages Router через интеграцию с React](#growing-beyond-the-pages-router-by-aligning-with-react) + +По мере роста популярности Next.js и создания более масштабных приложений мы получили обратную связь от сообщества и выявили области, где начали достигать пределов возможностей Pages Router. + +Наиболее заметно, что Pages Router не был разработан для потоковой передачи (streaming) — фундаментальной концепции современного React, которая помогает решать ограничения, с которыми мы столкнулись, и реализовать долгосрочное видение Next.js. + +Создание API фреймворка, поддерживающих потоковую передачу для получения данных, загрузки ресурсов и метаданных страниц, а также использование новых возможностей React потребовали значительных изменений в базовой архитектуре Next.js. + +Мы воспользовались возможностью построить систему на основе [новейших конкурентных возможностей React](https://react.dev/blog/2023/05/03/react-canaries), таких как Server Components, Suspense и других, которые были [разработаны для потоковых архитектур](https://github.com/reactwg/react-18/discussions/37). + +### [Постепенное внедрение — обязательное условие](#incremental-adoption-is-non-negotiable) + +Мы не хотели, чтобы наше сообщество было вынуждено полностью переписывать приложения для обновления до последней версии Next.js. Мы считаем, что постепенное внедрение — лучшая стратегия для эволюции приложений со временем. + +* **Постепенная миграция по маршрутам**: Без полного переписывания приложения вы можете перенести отдельный маршрут на App Router и начать использовать новые функции в удобном для вас темпе. См. наше [руководство по постепенному внедрению](/docs/app/building-your-application/upgrading/app-router-migration) или [посмотрите обучающее видео](https://www.youtube.com/watch?v=YQMSietiFm0). +* **Простой откат**: Если вас не устраивает производительность или удобство работы с App Router, вы можете легко вернуться к Pages Router для конкретного маршрута. + +Мы исследуем дополнительные возможности для ещё большего упрощения постепенного внедрения. + +### [Путь к стабильности](#road-to-stability) + +Мы начали разработку App Router для Next.js более года назад и с тех пор последовательно выпускаем новые функции и улучшения. + +* **Первое объявление**: В мае того года мы [опубликовали RFC](/blog/layouts-rfc), чтобы обозначить наши планы по повышению гибкости маршрутизации и макетов. +* **Ранняя бета-версия**: В Next.js 13 мы выпустили первую версию App Router, позволив сообществу опробовать её и предоставить раннюю обратную связь. +* **Стабильный API**: Учитывая обратную связь, мы сосредоточились на завершении основного API. В версии 13.4 мы объявили основное API App Router стабильным и готовым к широкому использованию. + +[Наши текущие приоритеты](#our-current-focus) +-------------------------------------------- + +Объявление стабильности сигнализировало сообществу, что основное API окончательно и не будет подвергаться значительным изменениям, требующим переписывания кода. + +С тех пор мы получили множество ценных отзывов, а увеличение использования неизбежно выявило ошибки и возможности для дальнейшего улучшения. + +Мы хотим, чтобы вы знали: мы **ещё не удовлетворены** опытом работы с App Router, и это наш главный приоритет на ближайшее время. Давайте обсудим работу, которую мы проводим для улучшения этого опыта. + +### [Улучшение производительности](#improving-performance) + +В ближайшие месяцы мы сосредоточимся на трёх аспектах производительности: скорости локальной разработки, времени сборки и производительности в serverless-среде. + +#### [Производительность локальной разработки](#local-development-performance) + +По мере развития Next.js и роста размера приложений, построенных на нём, мы постепенно заменяем части его базовой архитектуры более быстрыми и масштабируемыми инструментами. + +* **Прогресс миграции**: Мы начали с замены Babel _(компиляция)_ и Terser _(минификация)_ на [SWC](/docs/architecture/nextjs-compiler). Это помогло улучшить скорость локальной разработки и время сборки. + +* **Долгосрочные инвестиции**: Сохранение высокой производительности Fast Refresh независимо от размера приложения требует, чтобы Next.js работал как можно более инкрементально во время локальной разработки, пакетируя и компилируя код только по мере необходимости. + + Именно поэтому мы сейчас работаем над заменой webpack _(пакетирование)_ на [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack), который построен на движке инкрементальных вычислений низкого уровня, позволяющем кэшировать вплоть до отдельных функций. + + Приложения Next.js, перешедшие на Turbopack, увидят устойчивое улучшение скорости Fast Refresh даже при увеличении их размера. + + В последние несколько месяцев команда Turbo сосредоточилась на улучшении производительности Turbopack и поддержки всех функций Next.js и API App Router. + + Turbopack сейчас [доступен в бета-версии](/docs/architecture/turbopack) (`next dev --turbo`). + +* **Улучшение текущей архитектуры**: Помимо инвестиций в будущее, мы продолжаем вносить улучшения производительности в нашу текущую архитектуру на основе webpack. + + Для некоторых приложений Next.js, особенно тех, которые обновляют тысячи модулей, мы получали сообщения о нестабильности локальной разработки и Fast Refresh. Мы работаем над улучшением производительности и надёжности в этой области. Например, мы недавно добавили предварительно настроенные параметры (`modularizeImports`) для работы с [большими библиотеками иконок](https://github.com/vercel/next.js/pull/50900), которые могут случайно заставлять тысячи модулей перезагружаться при каждом запросе. + + +#### [Производительность сборки](#build-time-performance) + +Мы также работаем над сборкой production-версий с Turbopack (`next build --turbo`) и уже [начали внедрять](https://github.com/vercel/next.js/pull/51546) первые части этой работы. Ожидайте больше обновлений в предстоящих релизах. + +#### [Производительность в production](#production-performance) + +Наконец, в Vercel мы работаем над оптимизацией производительности и использования памяти Vercel Functions, [определяемых через код приложения Next.js](https://vercel.com/blog/framework-defined-infrastructure), обеспечивая минимальное время холодного старта при сохранении преимуществ масштабируемой serverless-архитектуры. Эта работа привела к появлению новых [возможностей трассировки](/docs/app/building-your-application/optimizing/open-telemetry) (экспериментальных) в Next.js и первым исследованиям в области серверных инструментов для разработчиков. + +[Повышение стабильности](#improving-stability) +--------------------------------------------- + +Pages Router существует уже шесть лет. Выпуск App Router означал введение новых API, которым всего шесть месяцев. Мы прошли долгий путь за короткое время, но есть ещё возможности для улучшений по мере того, как мы узнаём больше от нашего сообщества и их опыта использования. + +Мы благодарны сообществу за готовность активно внедрять App Router и предоставлять обратную связь. Было множество отчётов об ошибках, которые мы исследуем, и мы благодарны за минимальные воспроизведения, которые вы создали, чтобы помочь изолировать проблемы и проверить исправления. + +Начиная с версии 13.4, мы уже исправили ряд серьёзных ошибок, влияющих на стабильность, которые доступны в последнем патче (`13.4.7`). Мы продолжим интенсивно работать над производительностью и стабильностью. + +[Развитие образовательных материалов для разработчиков](#improving-developer-education) +-------------------------------------------------------------------------------------- + +Хотя мы считаем, что новые функции App Router и современного React мощные, они также требуют дополнительного обучения и документации, чтобы помочь освоить эти новые концепции. + +### [Функции Next.js](#nextjs-features) + +В течение последнего года мы работали над полной переработкой документации Next.js. Эта работа теперь доступна на [nextjs.org/docs](/docs). Мы хотели бы выделить некоторые [важные моменты](https://twitter.com/delba_oliveira/status/1664323492077256704): + +* **Переключение между Pages и App**: Вы можете переключаться между изучением документации Pages Router или App Router с помощью кнопки в левой части документации. Кроме того, вы можете фильтровать результаты поиска в зависимости от выбранного роутера. +* **Улучшенное содержание и архитектура информации**: Почти каждая страница документации App Router была обновлена, включая более чёткую структуру и связность между страницами, а также сотни новых иллюстраций, чтобы визуально объяснить, как работает Next.js. +* **Ещё впереди**: Здесь нам предстоит ещё много работы. Команда Developer Experience в Vercel усердно трудится над созданием дополнительных учебных ресурсов (включая обновлённый курс на `/learn`, посвящённый App Router) и примеров реальных кодовых баз (включая переработку [Next.js Commerce](https://github.com/vercel/commerce)). + +Мы будем выпускать новый контент в [документации](/docs), на [Twitter](https://twitter.com/nextjs), [YouTube](https://www.youtube.com/c/VercelHQ) и других платформах. + +### [Новые функции React](#new-react-features) + +Мы также услышали ваши отзывы о необходимости обучения новым функциям React, доступным в App Router Next.js. + +* **Server Components**: Важно отметить, что такие функции, как Server Components, и соглашения, такие как директива [`"use client"`](https://github.com/reactjs/rfcs/blob/main/text/0227-server-module-conventions.md), не являются специфичными для Next.js, а представляют собой часть более широкой экосистемы React. + + Наша команда, наши партнёры в Meta и другие независимые участники работают над предоставлением большего количества обучающих материалов по этим темам. Эти концепции ещё молоды, но мы уверены в экосистеме React и [продолжающемся обучении](https://github.com/reactwg/server-components/discussions/5). + +* **Client Components**: В свете недавних обсуждений Server Components важно отметить, что клиентские компоненты _не_ являются деоптимизацией. Клиент — валидная часть модели React, и он никуда не исчезает. + + Вы можете рассматривать клиентские компоненты как существующую сегодня экосистему Next.js, где ваши любимые библиотеки и инструменты продолжают работать. Например, частый вопрос, который мы видим: нужно ли добавлять `"use client"` в каждый файл, чтобы сделать его клиентским компонентом. Это не обязательно, но мы понимаем, что эти концепции новые и потребуется время для их изучения. Вам нужно только [обозначить верхнюю границу](/docs/getting-started/react-essentials#the-use-client-directive), где ваш код переходит с сервера на клиент. Эта архитектура позволяет вам [переплетать серверные и клиентские компоненты](https://github.com/reactwg/server-components/discussions/5). + +* **Развитие сторонней экосистемы**: Помимо обучения, экосистема вокруг новых функций React продолжает расти. Например, [Panda CSS](https://panda-css.com/), CSS-in-JS библиотека от создателей Chakra UI, недавно объявила о поддержке React Server Components. + +* **Server Actions (альфа)**: [Server Actions](/docs/app/building-your-application/data-fetching/server-actions) позволяют выполнять мутации данных на сервере, уменьшают клиентский JavaScript и обеспечивают прогрессивное улучшение форм. Мы пока не рекомендуем использовать Server Actions в production. Мы благодарны за ранние отзывы тестировщиков альфа-версии, которые помогают нам формировать будущее этой функции. + + +[Благодарности](#thank-you) +--------------------------- + +Мы благодарны многим из вас за выбор Next.js для обучения и разработки. + +Наша сосредоточенность на производительности, стабильности и удобстве разработчиков будет отражена в предстоящих релизах Next.js. Мы хотим, чтобы работа с Next.js была приятной — и делала вас (и вашу команду) более продуктивными. + +Как всегда, мы очень ценим вашу обратную связь. Если вы столкнулись с какими-либо проблемами в Next.js, пожалуйста, [создайте issue](https://github.com/vercel/next.js/issues/new/choose) или [начните новое обсуждение](https://github.com/vercel/next.js/discussions), и мы изучим их. \ No newline at end of file diff --git a/apps/docs/content/ru/blog/layouts-rfc.mdx b/apps/docs/content/ru/blog/layouts-rfc.mdx new file mode 100644 index 00000000..c790acf9 --- /dev/null +++ b/apps/docs/content/ru/blog/layouts-rfc.mdx @@ -0,0 +1,911 @@ +--- +source-updated-at: 2025-05-29T19:07:21.000Z +translation-updated-at: 2025-06-02T19:47:16.311Z +title: RFC по макетам +description: >- + Вложенные маршруты и макеты, клиентская и серверная маршрутизация, функции React 18, + и дизайн для серверных компонентов. +author: + - name: Дельба де Оливейра + image: /static/team/delba.jpg + - name: Ли Робинсон + image: /static/team/lee.jpg + - name: Себастьян Маркбоге + image: /static/team/seb.jpg + - name: Тим Нойткенс + image: /static/team/tim.jpg +date: 2022-05-23T20:30:00.507Z +image: >- + https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/twitter-card.png +--- + +Этот RFC (Request for Comment) представляет собой самое крупное обновление Next.js с момента его появления в 2016 году: + +* **Вложенные макеты:** Создавайте сложные приложения с вложенными маршрутами. +* **Оптимизировано для серверных компонентов:** Улучшена навигация по поддеревьям. +* **Улучшенная загрузка данных:** Загрузка в макетах без водопадов запросов. +* **Использование функций React 18:** Потоковая передача, переходы и Suspense. +* **Клиентская и серверная маршрутизация:** Сервероцентричная маршрутизация с поведением, подобным _SPA_. +* **100% инкрементальная адаптация:** Без критических изменений для постепенного внедрения. +* **Продвинутые шаблоны маршрутизации:** Параллельные маршруты, перехватывающие маршруты и многое другое. + +Новый маршрутизатор Next.js будет построен на основе [недавно выпущенных функций React 18](https://reactjs.org/blog/2022/03/29/react-v18.html). Мы планируем ввести стандарты и соглашения, которые позволят легко адаптировать эти новые функции и воспользоваться их преимуществами. + +> Работа над этим RFC продолжается, и мы объявим, когда новые функции станут доступны. Чтобы оставить отзыв, присоединяйтесь к обсуждению на [Github Discussions](https://github.com/vercel/next.js/discussions/37136). + +[Содержание](#содержание) +--------------------------------------- + +* [Мотивация](#мотивация) +* [Терминология](#терминология) +* [Как работает маршрутизация сейчас](#как-работает-маршрутизация-сейчас) +* [Директория `app`](#введение-в-маршрутизатор-app) +* [Определение маршрутов](#определение-маршрутов) +* [Макеты](#макеты) +* [Страницы](#страницы) +* [Серверные компоненты React](#серверные-компоненты-react) +* [Загрузка данных](#загрузка-данных) +* [Группы маршрутов (новое)](#группы-маршрутов) +* [Сервероцентричная маршрутизация (новое)](#сервероцентричная-маршрутизация) +* [Мгновенные состояния загрузки (новое)](#мгновенные-состояния-загрузки) +* [Обработка ошибок (новое)](#обработка-ошибок) +* [Шаблоны (новое)](#шаблоны) +* [Продвинутые шаблоны маршрутизации (новое)](#продвинутые-шаблоны-маршрутизации) +* [Заключение](#заключение) + +[Мотивация](#мотивация) +------------------------- + +Мы собирали отзывы сообщества с GitHub, Discord, Reddit и нашего опроса разработчиков о текущих ограничениях маршрутизации в Next.js. Мы обнаружили, что: + +* Опыт разработки при создании макетов можно улучшить. Должно быть легко создавать вложенные макеты, которые можно использовать на нескольких маршрутах и сохранять их состояние при навигации. +* Многие приложения Next.js — это панели управления или консоли, которые выиграют от более продвинутых решений маршрутизации. + +Хотя текущая система маршрутизации хорошо работала с самого начала Next.js, мы хотим упростить разработчикам создание более производительных и функциональных веб-приложений. + +Как сопровождающие фреймворка, мы также хотим создать систему маршрутизации, которая будет обратно совместима и соответствует будущему React. + +> **Примечание:** Некоторые соглашения по маршрутизации были вдохновлены маршрутизатором на основе Relay в Meta, где изначально разрабатывались некоторые функции серверных компонентов, а также клиентскими маршрутизаторами, такими как React Router и Ember.js. Соглашение о файле `layout.js` было вдохновлено работой, проделанной в SvelteKit. Мы также хотели бы поблагодарить [Кэссиди](https://twitter.com/cassidoo) за открытие [более раннего RFC по макетам](https://github.com/vercel/next.js/discussions/26389). + +[Терминология](#терминология) +--------------------------- + +Этот RFC вводит новые соглашения и синтаксис маршрутизации. Терминология основана на React и стандартных терминах веб-платформы. На протяжении RFC вы увидите ссылки на определения ниже. + +* **Дерево:** Соглашение для визуализации иерархической структуры. Например, дерево компонентов с родительскими и дочерними компонентами, структура папок и т.д. +* **Поддерево:** Часть дерева, начинающаяся с корня (первого) и заканчивающаяся листьями (последними). + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/terminology.png) + +* **Путь URL:** Часть URL, которая идет после домена. +* **Сегмент URL:** Часть пути URL, разделенная слешами. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/url-anatomy.png) + +[Как работает маршрутизация сейчас](#как-работает-маршрутизация-сейчас) +----------------------------------------------------------- + +Сегодня Next.js использует файловую систему для сопоставления отдельных папок и файлов в директории [Pages](/docs/pages/building-your-application/routing/pages-and-layouts) с маршрутами, доступными через URL. Каждый файл **страницы** экспортирует React-компонент и имеет связанный **маршрут** на основе имени файла. Например: + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/routing-today.png) + +* **Динамические маршруты:** Next.js поддерживает [Динамические маршруты](/docs/pages/building-your-application/routing/dynamic-routes) (включая варианты catch all) с соглашениями `[param].js`, `[...param].js` и `[[...param]].js`. +* **Макеты:** Next.js предлагает поддержку простых [макетов на основе компонентов](/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern), макетов для отдельных страниц с использованием [шаблона свойства компонента](/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern#per-page-layouts) и единого глобального макета с использованием [пользовательского приложения](/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern#single-shared-layout-with-custom-app). +* **Загрузка данных:** Next.js предоставляет методы загрузки данных ([`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props), [`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props)), которые можно использовать на уровне страницы (маршрута). Эти методы используются для определения, должна ли страница быть статически сгенерирована ([`getStaticProps`](/docs/pages/building-your-application/data-fetching/get-static-props)) или отрендерена на стороне сервера ([`getServerSideProps`](/docs/pages/building-your-application/data-fetching/get-server-side-props)). Кроме того, вы можете использовать [Инкрементальную статическую регенерацию (ISR)](/docs/pages/building-your-application/data-fetching/incremental-static-regeneration) для создания или обновления статических страниц после сборки сайта. +* **Рендеринг:** Next.js предоставляет три варианта рендеринга: [Статическая генерация](https://nextjs.org/learn/foundations/how-nextjs-works/rendering), [Рендеринг на стороне сервера](https://nextjs.org/learn/foundations/how-nextjs-works/rendering) и [Рендеринг на стороне клиента](https://nextjs.org/learn/foundations/how-nextjs-works/rendering). По умолчанию страницы статически генерируются, если у них нет блокирующего требования к загрузке данных (`getServerSideProps`). + +[Введение в директорию `app`](#введение-в-директорию-app) +----------------------------------------------------------------- + +Чтобы гарантировать, что эти новые улучшения могут быть инкрементально приняты и избежать критических изменений, мы предлагаем новую директорию под названием `app`. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/app-folder.png) + +Директория `app` будет работать вместе с директорией `pages`. Вы можете постепенно перемещать части вашего приложения в новую директорию `app`, чтобы воспользоваться новыми функциями. Для обратной совместимости поведение директории `pages` останется прежним и будет продолжать поддерживаться. + +[Определение маршрутов](#определение-маршрутов) +----------------------------------- + +Вы можете использовать **иерархию папок** внутри `app` для определения маршрутов. **Маршрут** — это единый путь вложенных папок, следующий иерархии от **корневой папки** до конечной **листовой папки.** + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/routes.png) + +Например, вы можете добавить новый маршрут `/dashboard/settings`, вложив две новые папки в директорию `app`. + +> **Примечание:** +> +> * В этой системе вы будете использовать папки для определения маршрутов, а файлы — для определения UI (с новыми соглашениями о файлах, такими как `layout.js`, `page.js`, и во второй части RFC `loading.js`). +> * Это позволяет размещать ваши собственные файлы проекта (компоненты UI, тесты, истории и т.д.) внутри директории `app`. В настоящее время это возможно только с [конфигурацией pageExtensions](/docs/pages/api-reference/next-config-js/pageExtensions#including-non-page-files-in-the-pages-directory). + +### [Сегменты маршрута](#сегменты-маршрута) + +Каждая папка в [поддереве](#терминология) представляет **сегмент маршрута**. Каждый сегмент маршрута сопоставляется с соответствующим **сегментом** в **[пути URL](#терминология)**. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/route-segments.png) + +Например, маршрут `/dashboard/settings` состоит из 3 сегментов: + +* Корневой сегмент `/` +* Сегмент `dashboard` +* Сегмент `settings` + +> **Примечание:** Название **сегмент маршрута** было выбрано для соответствия существующей терминологии вокруг [путей URL](#терминология). + +[Макеты](#макеты) +------------------- + +**Новое соглашение о файлах:** `layout.js` + +До сих пор мы использовали папки для определения маршрутов нашего приложения. Но пустые папки сами по себе ничего не делают. Давайте обсудим, как вы можете определить UI, который будет отображаться для этих маршрутов, используя новые соглашения о файлах. + +**Макет** — это UI, общий для сегментов маршрута в [поддереве](#терминология). Макеты не влияют на [пути URL](#терминология) и не перерендериваются (состояние React сохраняется), когда пользователь переходит между родственными сегментами. + +Макет можно определить, экспортировав React-компонент по умолчанию из файла `layout.js`. Компонент должен принимать проп `children`, который будет заполнен сегментами, которые макет оборачивает. + +Существует 2 типа макетов: + +* **Корневой макет:** Применяется ко всем маршрутам +* **Обычный макет:** Применяется к определенным маршрутам + +Вы можете вложить два или более макетов вместе, чтобы сформировать **вложенные макеты**. + +### [Корневой макет](#корневой-макет) + +Вы можете создать корневой макет, который будет применяться ко всем маршрутам вашего приложения, добавив файл `layout.js` внутри папки `app`. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/root-layout.png) + +> **Примечание:** +> +> * Корневой макет заменяет необходимость в [пользовательском приложении (`_app.js`)](/docs/pages/building-your-application/routing/custom-app) и [пользовательском документе (`_document.js`)](/docs/pages/building-your-application/routing/custom-document), поскольку он применяется ко всем маршрутам. +> * Вы сможете использовать корневой макет для настройки начальной оболочки документа (например, тегов `` и ``). +> * Вы сможете загружать данные внутри корневого макета (и других макетов). + +### [Обычные макеты](#обычные-макеты) + +Вы также можете создать макет, который применяется только к части вашего приложения, добавив файл `layout.js` внутри конкретной папки. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/regular-layouts.png) + +Например, вы можете создать файл `layout.js` внутри папки `dashboard`, который будет применяться только к сегментам маршрута внутри `dashboard`. + +### [Вложенные макеты](#вложенные-макеты) + +Макеты по умолчанию **вложены**. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/nested-layouts.png) + +Например, если мы объединим два макета выше. Корневой макет (`app/layout.js`) будет применен к макету `dashboard`, который также будет применен ко всем сегментам маршрута внутри `dashboard/*`. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/nested-layouts-example.png) + +[Страницы](#страницы) +--------------- + +**Новое соглашение о файлах:** `page.js` + +Страница — это UI, уникальный для сегмента маршрута. Вы можете создать страницу, добавив файл `page.js` внутри папки. + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/page.png) + +Например, чтобы создать страницы для маршрутов `/dashboard/*`, вы можете добавить файл `page.js` внутри каждой папки. Когда пользователь посещает `/dashboard/settings`, Next.js отрендерит файл `page.js` для папки `settings`, обернутый в любые макеты, существующие выше по [поддереву](#терминология). + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/page-example.png) + +Вы можете создать файл `page.js` непосредственно внутри папки dashboard, чтобы соответствовать маршруту `/dashboard`. Макет dashboard также будет применен к этой странице: + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/page-nested.png) + +Этот маршрут состоит из 2 сегментов: + +* Корневой сегмент `/` +* Сегмент `dashboard` + +> **Примечание:** +> +> * Чтобы маршрут был валидным, он должен иметь страницу в своем листовом сегменте. Если её нет, маршрут вызовет ошибку. + +### [Поведение макета и страницы](#поведение-макета-и-страницы) + +* Расширения файлов `js|jsx|ts|tsx` могут использоваться для страниц и макетов. +* Компоненты страниц — это экспорт по умолчанию из `page.js`. +* Компоненты макетов — это экспорт по умолчанию из `layout.js`. +* Компоненты макетов **должны** принимать проп `children`. + +Когда компонент макета рендерится, проп `children` будет заполнен дочерним макетом (если он существует дальше по [поддереву](#терминология)) или страницей. + +Это может быть проще визуализировать как [дерево](#терминология) макетов, где родительский макет будет выбирать ближайший дочерний макет, пока не достигнет страницы. + +**Пример:** + +![](https://h8DxKfmAPhn8O0p3.public.blob.vercel-storage.com/static/blog/layouts-rfc/basic-example.png) + +```js filename="app/layout.js" +// Корневой макет +// - Применяется ко всем маршрутам +export default function RootLayout({ children }) { + return ( + + +
+ {children} +