1. Вспоминаем, что мы изучили
Итак, мы фактически научились строить полный цикл взаимодействия: от пользователя в браузере до вашего Node.js-сервера и обратно, используя самые современные и эффективные подходы в Next.js.
Допустим, что вы строите дом.
- Route Handlers — это как прочная внешняя лестница, которая ведёт к задней двери вашего дома. Через неё могут зайти любые "гости" (другие приложения, мобильные клиенты, другие части вашего же фронтенда), передать "посылки" (данные) и получить "ответы". Она универсальна и понятна всем. Вы задаёте чёткие правила: "для посылок типа POST сюда", "для GET туда".
- Server Actions — это как секретный телепорт, встроенный прямо в вашу мебель в гостиной. Вы просто нажимаете кнопку (отправляете форму), и данные мгновенно переносятся прямо на сервер, делают своё дело, а результат появляется обратно, не требуя от вас ручной прокладки проводов (fetch-запросов). Он выглядит как обычная кнопка, но внутри — магия!
Обе эти технологии — Route Handlers и Server Actions — работают на Node.js, но по-разному интегрированы в Next.js. Они позволяют нам перенести тяжёлую работу (доступ к базе данных, сложные вычисления, обработка файлов) с клиентского браузера на сервер, где она выполняется быстрее и безопаснее.
Пример: Как это выглядит в нашем приложении (концептуально)
Давайте представим, что наше приложение — это "Список дел".
Создание задачи (через Server Action):
Мы могли бы иметь форму на странице, где пользователь вводит текст задачи. При отправке формы, вместо того чтобы вручную делать fetch('/api/todos'), мы просто указываем action={createTodo}. Функция createTodo на сервере получает данные, сохраняет их (например, в файл или базу данных), и Next.js сам обновляет UI.
// app/add-todo/page.tsx
import { addTodo } from './actions'; // Импортируем Server Action
export default function AddTodoPage() {
return (
<form action={addTodo}> {/* Прямая привязка к Server Action */}
<input type="text" name="title" placeholder="Что нужно сделать?" />
<button type="submit">Добавить задачу</button>
</form>
);
}
// app/add-todo/actions.ts
'use server'; // Директива, указывающая, что это Server Action
import fs from 'fs/promises';
import path from 'path';
export async function addTodo(formData: FormData) {
const title = formData.get('title') as string;
if (!title) {
throw new Error('Название задачи не может быть пустым!');
}
// ... логика сохранения задачи, например, в JSON файл
const filePath = path.join(process.cwd(), 'data', 'todos.json');
const data = await fs.readFile(filePath, 'utf8');
const todos = JSON.parse(data);
todos.push({ id: Date.now(), title, completed: false });
await fs.writeFile(filePath, JSON.stringify(todos, null, 2));
console.log('Задача добавлена на сервере!');
}
Получение списка задач (через Route Handler):
Если другому приложению (или даже нашему же, но в другом месте, где Server Actions не подходят) нужен список задач, мы можем обратиться к API-эндпоинту:
// app/api/todos/route.ts
import { NextResponse } from 'next/server';
import fs from 'fs/promises';
import path from 'path';
export async function GET() {
try {
const filePath = path.join(process.cwd(), 'data', 'todos.json');
const data = await fs.readFile(filePath, 'utf8');
const todos = JSON.parse(data);
return NextResponse.json(todos, { status: 200 });
} catch (error) {
console.error('Ошибка при чтении задач:', error);
return NextResponse.json({ message: 'Ошибка сервера' }, { status: 500 });
}
}
И этот эндпоинт будет доступен по адресу /api/todos. Любой, кто отправит GET-запрос по этому адресу, получит список задач в формате JSON.
Как видите, задачи, которые требуют взаимодействия с сервером, могут быть решены обеими технологиями, но их назначение и способ использования немного различаются.
2. Часто задаваемые вопросы
Теперь давайте разберем те вопросы, которые, я уверен, возникают в вашей голове, когда речь заходит о Server Actions и Route Handlers. Это, пожалуй, самый "горячий" и дискуссионный момент этого модуля.
Когда использовать Route Handlers (API Routes), а когда Server Actions?
Это самый главный вопрос! И, как это часто бывает в программировании, ответ: "Зависит от ситуации".
Используйте Route Handlers (API Routes), когда:
- Вы строите полноценный REST API, который будет использоваться не только вашим Next.js-приложением, но и:
- Мобильными приложениями (iOS, Android).
- Сторонними сервисами.
- Другими фронтенд-приложениями (например, на React без Next.js).
- Вам нужен более традиционный API-слой для интеграции.
- Вам нужны HTTP-методы (GET, POST, PUT, DELETE) и HTTP-статусы в их классическом понимании для каждого запроса. Route Handlers строго следуют HTTP-спецификации.
- Вам нужен контроль над заголовками запроса/ответа, CORS и прочими низкоуровневыми аспектами HTTP.
- Вы работаете с файлами, особенно с большими файлами или потоковой передачей, где нужен прямой контроль над телом запроса/ответа.
- Вам нужна публичная, документированная точка входа для данных, к которой могут обращаться кто угодно, при наличии прав.
Используйте Server Actions, когда:
- Вы выполняете мутации данных (CRUD операции) в рамках форм в вашем Next.js-приложении. Это самый распространённый и удобный сценарий. action={myServerAction} — и всё работает!
- Вы хотите максимально упростить взаимодействие между клиентским компонентом и сервером, минимизировав количество шаблонного кода (fetch, парсинг JSON, обработка ошибок сетевых запросов). Server Actions абстрагируют большую часть этой рутины.
- Вам нужен "оптимистичный UI" (useOptimistic) или удобное управление состоянием формы (useFormState). Эти хуки React напрямую интегрированы с Server Actions.
- Ваша серверная логика тесно связана с конкретными компонентами UI. Например, кнопка "Лайк" на посте — её действие может быть Server Action.
- Вам нужно избежать дополнительных сетевых запросов в браузере при отправке формы, так как Server Actions используют прямую POST-передачу данных без AJAX (хотя под капотом Next.js это все же делает).
3. Сводная таблица сравнения
Давайте сведем все это в одну небольшую, но очень полезную таблицу:
| Характеристика | Route Handlers (API Routes) | Server Actions |
|---|---|---|
| Основное назначение | Построение универсального REST API | Выполнение серверной логики напрямую из компонентов/форм |
| HTTP-методы | Чётко определены: GET, POST, PUT, DELETE и др. | Всегда POST (для безопасности), остальные методы неявно внутри действия |
| Интеграция с UI | Через fetch() на клиенте | Прямое подключение к form action или вызов из любого компонента |
| Взаимодействие с внешними клиентами | Отлично подходит для мобильных, других фронтендов | В основном для взаимодействия между клиентским кодом Next.js и сервером Next.js |
| Кеширование | Можно контролировать кеширование HTTP-заголовками | Интегрированы с системой кеширования Next.js (revalidatePath, revalidateTag) |
| Обработка ошибок | Возврат NextResponse.json({ message: 'Error' }, { status: 400 }) | throw new Error(), обработка через useFormState или error.tsx |
| Оптимистичный UI | Требует ручной реализации с fetch | Встроенная поддержка через useOptimistic |
| Валидация данных | Обычно на сервере (например, zod) | Обычно на сервере (например, zod), часто интегрирована с useFormState |
| Сложность внедрения | Чуть больше шаблонного кода (fetch, парсинг, try/catch) | Меньше шаблонного кода, "магическая" интеграция |
| Когда выбирать | Для публичных API, интеграции, строгих REST-конвенций | Для обработки форм, мутаций данных, интерактивности внутри Next.js-приложения |
Надеюсь, эта таблица поможет вам принять более осознанное решение. Помните, что они не исключают, а дополняют друг друга. Часто вы будете использовать и то, и другое в одном проекте!
4. Как ваш проект развивать дальше?
С этими знаниями, ваше учебное приложение может стать по-настоящему интерактивным. Мы можем:
- Добавить формы для создания, редактирования и удаления студентов/задач.
- Реализовать API для получения списка студентов, который можно использовать на отдельной странице админки или даже в мобильном приложении.
- Применять useOptimistic для мгновенного обновления интерфейса при добавлении новой задачи, даже если сервер ещё не ответил, создавая ощущение невероятной скорости.
- Добавить валидацию форм, чтобы пользователи не могли ввести некорректные данные.
Вы перешли от простого отображения статических данных к полноценному динамическому веб-приложению, способному взаимодействовать с серверной частью! Думаю вам понравилось изучать Next, а работать с ним понравиться еще больше!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ