Українська

Дізнайтеся, як створювати потужні кінцеві точки API за допомогою обробників маршрутів Next.js. Цей посібник охоплює все: від базового налаштування до передових технік, з практичними прикладами та найкращими практиками.

Обробники маршрутів (Route Handlers) у Next.js: Повний посібник зі створення кінцевих точок API

Next.js революціонізував спосіб створення веб-додатків завдяки своїм потужним функціям, таким як рендеринг на стороні сервера, генерація статичних сайтів, а тепер — обробники маршрутів (Route Handlers). Обробники маршрутів надають гнучкий та ефективний спосіб створення кінцевих точок API безпосередньо у вашому додатку Next.js. Цей посібник розглядає концепцію обробників маршрутів, їхні переваги та способи їх ефективного використання для створення надійних API.

Що таке обробники маршрутів (Route Handlers) у Next.js?

Обробники маршрутів — це функції, визначені в каталозі app проекту Next.js, які обробляють вхідні HTTP-запити. На відміну від старого підходу з pages/api (який використовує API Routes), обробники маршрутів пропонують більш оптимізований і гнучкий спосіб визначення кінцевих точок API поряд з вашими компонентами React. По суті, це безсерверні функції, що виконуються на межі (edge) або у вибраному вами серверному середовищі.

Вважайте обробники маршрутів бекенд-логікою вашого додатку Next.js, відповідальною за обробку запитів, взаємодію з базами даних та повернення відповідей.

Переваги використання обробників маршрутів

Налаштування вашого проекту Next.js

Перш ніж занурюватися в обробники маршрутів, переконайтеся, що у вас налаштований проект Next.js з каталогом app. Якщо ви починаєте новий проект, використовуйте таку команду:

npx create-next-app@latest my-nextjs-app

Під час процесу налаштування виберіть каталог app, щоб увімкнути нову систему маршрутизації.

Створення вашого першого обробника маршрутів

Створімо просту кінцеву точку API, яка повертає відповідь у форматі JSON. Створіть новий каталог у каталозі app, наприклад, /app/api/hello. Усередині цього каталогу створіть файл з назвою route.ts (або route.js, якщо ви не використовуєте TypeScript).

Ось код вашого першого обробника маршрутів:

// app/api/hello/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Привіт від обробників маршрутів Next.js!' });
}

Пояснення:

Тепер ви можете отримати доступ до цієї кінцевої точки, перейшовши за адресою /api/hello у вашому браузері або використовуючи інструменти, такі як curl або Postman.

Обробка різних HTTP-методів

Обробники маршрутів підтримують різні HTTP-методи, такі як GET, POST, PUT, DELETE, PATCH та OPTIONS. Ви можете визначити окремі функції для кожного методу в одному файлі route.ts.

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Логіка для отримання всіх користувачів з бази даних
 const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Приклад даних
 return NextResponse.json(users);
}

export async function POST(request: Request) {
 const data = await request.json(); // Парсимо тіло запиту як JSON
 // Логіка для створення нового користувача в базі даних з використанням 'data'
 const newUser = { id: 3, name: data.name, email: data.email }; // Приклад
 return NextResponse.json(newUser, { status: 201 }); // Повертаємо нового користувача зі статусом 201 Created
}

Пояснення:

Доступ до даних запиту

Об'єкт request надає доступ до різноманітної інформації про вхідний запит, включаючи заголовки, параметри запиту та тіло запиту.

Заголовки

Ви можете отримати доступ до заголовків запиту за допомогою властивості request.headers:

export async function GET(request: Request) {
 const userAgent = request.headers.get('user-agent');
 console.log('User Agent:', userAgent);
 return NextResponse.json({ userAgent });
}

Параметри запиту

Щоб отримати доступ до параметрів запиту, ви можете використовувати конструктор URL:

export async function GET(request: Request) {
 const url = new URL(request.url);
 const searchParams = new URLSearchParams(url.search);
 const id = searchParams.get('id');
 console.log('ID:', id);
 return NextResponse.json({ id });
}

Тіло запиту

Для запитів POST, PUT та PATCH ви можете отримати доступ до тіла запиту за допомогою методів request.json() або request.text(), залежно від типу контенту.

export async function POST(request: Request) {
 const data = await request.json();
 console.log('Data:', data);
 return NextResponse.json({ receivedData: data });
}

Повернення відповідей

Об'єкт NextResponse використовується для конструювання відповідей API. Він надає кілька методів для встановлення заголовків, кодів стану та тіла відповіді.

JSON-відповіді

Використовуйте метод NextResponse.json() для повернення JSON-відповідей:

return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });

Текстові відповіді

Використовуйте конструктор new Response() для повернення відповідей у вигляді простого тексту:

return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });

Перенаправлення

Використовуйте NextResponse.redirect() для перенаправлення користувачів на іншу URL-адресу:

import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.redirect(new URL('/new-location', request.url));
}

Встановлення заголовків

Ви можете встановлювати власні заголовки, використовуючи опцію headers в NextResponse.json() або new Response():

return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });

Інтеграція з проміжним ПЗ (Middleware)

Проміжне ПЗ (Middleware) дозволяє вам виконувати код до того, як запит буде оброблено вашим обробником маршрутів. Це корисно для автентифікації, авторизації, логування та інших наскрізних завдань.

Щоб створити проміжне ПЗ, створіть файл з назвою middleware.ts (або middleware.js) у каталозі app або будь-якому його підкаталозі. Проміжне ПЗ буде застосовуватися до всіх маршрутів у цьому каталозі та його підкаталогах.

// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/protected/:path*'], // Застосувати це проміжне ПЗ до шляхів, що починаються з /protected/
};

Пояснення:

Обробка помилок

Правильна обробка помилок є надзвичайно важливою для створення надійних API. Ви можете використовувати блоки try...catch для обробки винятків і повернення відповідних відповідей про помилки.

export async function GET(request: Request) {
 try {
 // Симулюємо помилку
 throw new Error('Щось пішло не так!');
 } catch (error: any) {
 console.error('Error:', error);
 return NextResponse.json({ error: error.message }, { status: 500 });
 }
}

Пояснення:

Потокові відповіді

Обробники маршрутів підтримують потокові відповіді, що дозволяє надсилати дані клієнту поступово. Це особливо корисно для великих наборів даних або тривалих процесів.

import { Readable } from 'stream';
import { NextResponse } from 'next/server';

async function* generateData() {
 for (let i = 0; i < 10; i++) {
 await new Promise(resolve => setTimeout(resolve, 500)); // Симулюємо затримку
 yield `Частина даних ${i}\n`;
 }
}

export async function GET(request: Request) {
 const readableStream = Readable.from(generateData());

 return new Response(readableStream, {
 headers: { 'Content-Type': 'text/plain; charset=utf-8' },
 });
}

Пояснення:

Автентифікація та авторизація

Захист ваших кінцевих точок API є критично важливим. Ви можете реалізувати автентифікацію та авторизацію за допомогою проміжного ПЗ або безпосередньо у ваших обробниках маршрутів.

Автентифікація

Автентифікація перевіряє особу користувача, який робить запит. Поширені методи автентифікації включають:

Ось приклад автентифікації JWT за допомогою проміжного ПЗ:

// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';

const secret = process.env.JWT_SECRET || 'ваш-секретний-ключ'; // Замініть на надійний, випадково згенерований секрет

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token')?.value;

 if (!token) {
 return NextResponse.json({ message: 'Потрібна автентифікація' }, { status: 401 });
 }

 try {
 jwt.verify(token, secret);
 return NextResponse.next();
 } catch (error) {
 return NextResponse.json({ message: 'Недійсний токен' }, { status: 401 });
 }
}

export const config = {
 matcher: ['/api/protected/:path*'],
};

Авторизація

Авторизація визначає, до яких ресурсів користувач має доступ. Зазвичай це базується на ролях або дозволах.

Ви можете реалізувати авторизацію у ваших обробниках маршрутів, перевіряючи ролі або дозволи користувача і повертаючи помилку, якщо він не має доступу.

// app/api/admin/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Припустимо, у вас є функція для отримання ролі користувача з токена або сесії
 const userRole = await getUserRole(request);

 if (userRole !== 'admin') {
 return NextResponse.json({ message: 'Неавторизовано' }, { status: 403 });
 }

 // Логіка для отримання даних адміністратора
 const adminData = { message: 'Дані адміністратора' };
 return NextResponse.json(adminData);
}

async function getUserRole(request: Request): Promise {
 // Замініть на вашу реальну логіку для вилучення ролі користувача із запиту
 // Це може включати перевірку JWT токена або сесії
 return 'admin'; // Приклад: жорстко закодована роль для демонстрації
}

Розгортання обробників маршрутів

Обробники маршрутів розгортаються як безсерверні функції на обраному вами хостинг-провайдері. Next.js підтримує різні платформи для розгортання, включаючи Vercel, Netlify, AWS та інші.

Для Vercel розгортання є простим: потрібно лише підключити ваш Git-репозиторій до Vercel і надіслати ваш код. Vercel автоматично визначає ваш проект Next.js і розгортає ваші обробники маршрутів як безсерверні функції.

Просунуті техніки

Edge-функції

Обробники маршрутів можна розгортати як Edge-функції, які виконуються на межі CDN, ближче до ваших користувачів. Це може значно зменшити затримку та покращити продуктивність.

Щоб розгорнути обробник маршрутів як Edge-функцію, додайте середовище виконання edge до вашого файлу route.ts:

export const runtime = 'edge';

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Привіт з Edge!' });
}

Серверні дії (Server Actions)

Серверні дії дозволяють виконувати серверний код безпосередньо з ваших компонентів React. Обробники маршрутів та серверні дії бездоганно працюють разом, дозволяючи вам з легкістю створювати складні додатки.

Ось приклад використання серверної дії для виклику обробника маршрутів:

// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';

async function handleSubmit(data: FormData) {
 'use server';

 const name = data.get('name');
 const email = data.get('email');

 const response = await fetch('/api/users', {
 method: 'POST',
 body: JSON.stringify({ name, email }),
 });

 if (response.ok) {
 router.refresh(); // Оновити сторінку, щоб відобразити зміни
 }
}

export default function MyComponent() {
 const router = useRouter();

 return (
 




); }

Кешування

Кешування може значно покращити продуктивність ваших кінцевих точок API. Ви можете використовувати заголовок Cache-Control для контролю того, як ваші відповіді кешуються браузерами та CDN.

return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });

Цей приклад встановлює заголовок Cache-Control на public, max-age=3600, що вказує браузерам та CDN кешувати відповідь протягом однієї години.

Найкращі практики

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

Ось кілька прикладів з реального світу, як можна використовувати обробники маршрутів:

Приклад міжнародної електронної комерції: Обробник маршрутів, що використовується для отримання цін на товари залежно від країни користувача. Кінцева точка може використовувати геолокацію запиту (отриману з IP-адреси) для визначення місцезнаходження користувача та повернення цін у відповідній валюті. Це сприяє локалізованому досвіду покупок.

Приклад глобальної автентифікації: Обробник маршрутів, що реалізує багатофакторну автентифікацію (MFA) для користувачів у всьому світі. Це може включати надсилання SMS-кодів або використання додатків-автентифікаторів, з дотриманням правил конфіденційності та телекомунікаційних інфраструктур різних регіонів.

Доставка багатомовного контенту: Обробник маршрутів, що доставляє контент бажаною для користувача мовою. Її можна визначити за заголовком `Accept-Language` у запиті. Цей приклад підкреслює необхідність правильного кодування UTF-8 та підтримки мов з написанням справа наліво, де це доречно.

Висновок

Обробники маршрутів Next.js надають потужний і гнучкий спосіб створення кінцевих точок API безпосередньо у вашому додатку Next.js. Використовуючи обробники маршрутів, ви можете з легкістю створювати надійні API, розміщувати свою бекенд-логіку поруч із компонентами React та використовувати такі функції, як проміжне ПЗ, потокова передача та Edge-функції.

Цей вичерпний посібник охопив усе, від базового налаштування до просунутих технік. Дотримуючись найкращих практик, викладених у цьому посібнику, ви зможете створювати високоякісні API, які є безпечними, продуктивними та легкими в підтримці.