Научете как да изграждате бекенд без сървър с Next.js API Routes. Ръководството покрива основна настройка, удостоверяване, съхранение на данни и други.
API маршрути в Next.js: Изграждане на вашия бекенд с лекота
Next.js направи революция във фронтенд разработката със своите мощни функции и интуитивна структура. Но знаехте ли, че може значително да опрости и разработката на бекенд? API маршрутите (API Routes) в Next.js ви позволяват да създавате безсървърни (serverless) API ендпойнти директно във вашето Next.js приложение, като в много случаи премахват необходимостта от отделен бекенд сървър. Това подробно ръководство ще ви преведе през процеса на изграждане на стабилен и мащабируем бекенд с помощта на Next.js API Routes.
Какво представляват API маршрутите в Next.js?
API маршрутите са безсървърни функции, които създавате в директорията /pages/api
във вашия Next.js проект. Тези функции обработват входящи HTTP заявки и връщат отговори, точно както традиционен бекенд API. Ключовата разлика е, че те се разгръщат като безсървърни функции, което означава, че не е нужно да управлявате сървъри или инфраструктура.
Мислете за тях като за леки бекенд функции при поискване, които са безпроблемно интегрирани с вашия Next.js фронтенд.
Предимства на използването на Next.js API Routes
- Опростена разработка: Пишете както фронтенд, така и бекенд кода си в един и същи проект, използвайки JavaScript или TypeScript. Край на превключването на контекста между различни проекти и технологии.
- Безсървърна архитектура: Възползвайте се от мащабируемостта, надеждността и икономическата ефективност на serverless технологиите. Плащате само за ресурсите, които консумирате.
- Лесно разгръщане: Разгърнете цялото си приложение (фронтенд и бекенд) с една команда, използвайки платформи като Vercel или Netlify.
- Вградена сигурност: Next.js и безсървърните платформи предоставят вградени функции за сигурност, за да защитят вашите API ендпойнти.
- Подобрена производителност: API маршрутите могат да бъдат разгърнати по-близо до вашите потребители, което намалява латентността и подобрява производителността, особено полезно за потребители в световен мащаб.
- Повторно използване на код: Споделяйте код между вашия фронтенд и бекенд, намалявайки дублирането на код и подобрявайки поддръжката.
Първи стъпки с Next.js API Routes
Нека създадем прост API маршрут, който връща JSON отговор. Първо, уверете се, че имате настроен Next.js проект. Ако не, създайте такъв с помощта на:
npx create-next-app my-app
cd my-app
Сега създайте файл с име hello.js
в директорията /pages/api
:
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
Този код дефинира прост API маршрут, който отговаря с JSON обект, съдържащ името „John Doe“. За достъп до този API маршрут, стартирайте вашия Next.js сървър за разработка:
npm run dev
След това отворете браузъра си и отидете на http://localhost:3000/api/hello
. Трябва да видите следния JSON отговор:
{"name": "John Doe"}
Разбиране на handler-а на API маршрута
Функцията handler
във вашия API маршрут получава два аргумента:
req
: Инстанция наhttp.IncomingMessage
, която съдържа информация за входящата заявка, като например метода на заявката, хедърите и тялото.res
: Инстанция наhttp.ServerResponse
, която ви позволява да изпратите отговор обратно към клиента.
Можете да използвате тези обекти, за да обработвате различни типове заявки, да четете данни от тялото на заявката, да задавате хедъри на отговора и да изпращате различни типове отговори.
Обработка на различни HTTP методи
Можете да използвате свойството req.method
, за да определите HTTP метода на входящата заявка и да обработвате различните методи съответно. Например:
// pages/api/method.js
export default function handler(req, res) {
if (req.method === 'GET') {
// Обработка на GET заявка
res.status(200).json({ message: 'Това е GET заявка' })
} else if (req.method === 'POST') {
// Обработка на POST заявка
res.status(200).json({ message: 'Това е POST заявка' })
} else {
// Обработка на други методи
res.status(405).json({ message: 'Методът не е разрешен' })
}
}
В този пример API маршрутът обработва както GET, така и POST заявки. Ако методът на заявката е GET, той отговаря с JSON обект, съдържащ съобщението „Това е GET заявка“. Ако методът на заявката е POST, той отговаря с JSON обект, съдържащ съобщението „Това е POST заявка“. Ако методът на заявката е друг, той отговаря с грешка 405 Method Not Allowed (Методът не е разрешен).
Четене на данни от тялото на заявката
При POST, PUT и PATCH заявки често се налага да четете данни от тялото на заявката. Next.js предоставя вградена поддръжка за парсване на JSON и URL-кодирани тела на заявки. За да парснете JSON тяло на заявка, можете да използвате свойството req.body
. Например:
// pages/api/post.js
export default async function handler(req, res) {
if (req.method === 'POST') {
const { name, email } = req.body
// Обработка на данните
console.log('Име:', name)
console.log('Имейл:', email)
res.status(200).json({ message: 'Данните са получени успешно' })
} else {
res.status(405).json({ message: 'Методът не е разрешен' })
}
}
За да тествате този API маршрут, можете да използвате инструмент като Postman или curl, за да изпратите POST заявка с JSON тяло:
curl -X POST -H "Content-Type: application/json" -d '{"name": "Jane Doe", "email": "jane.doe@example.com"}' http://localhost:3000/api/post
Задаване на хедъри на отговора
Можете да използвате метода res.setHeader()
, за да зададете хедъри на отговора. Това е полезно за задаване на типа на съдържанието, контрол на кеширането и друга важна информация. Например:
// pages/api/headers.js
export default function handler(req, res) {
res.setHeader('Content-Type', 'application/json')
res.setHeader('Cache-Control', 's-maxage=3600')
res.status(200).json({ message: 'Hello, world!' })
}
В този пример API маршрутът задава хедъра Content-Type
на application/json
, което показва, че отговорът е JSON обект. Той също така задава хедъра Cache-Control
на s-maxage=3600
, което казва на браузъра и CDN да кешират отговора за до 1 час.
Обработка на грешки
Важно е да обработвате грешките елегантно във вашите API маршрути. Можете да използвате try-catch блокове, за да улавяте изключения и да изпращате подходящи отговори за грешки към клиента. Например:
// pages/api/error.js
export default async function handler(req, res) {
try {
// Симулиране на грешка
throw new Error('Нещо се обърка')
} catch (error) {
console.error(error)
res.status(500).json({ message: 'Вътрешна грешка на сървъра' })
}
}
В този пример API маршрутът симулира грешка, като хвърля нов Error
обект. Блокът catch улавя грешката, записва я в конзолата и изпраща отговор 500 Internal Server Error (Вътрешна грешка на сървъра) към клиента. Обмислете използването на надеждна система за регистриране (logging) като Sentry или Datadog за производствени среди.
Свързване с база данни
Един от най-често срещаните случаи на употреба на API маршрути е свързването с база данни. Next.js API Routes се интегрират безпроблемно с различни бази данни, включително:
- MongoDB: Популярна NoSQL база данни, която е подходяща за гъвкави и неструктурирани данни.
- PostgreSQL: Мощна релационна база данни с отворен код, известна със своята надеждност и цялост на данните.
- MySQL: Друга популярна релационна база данни с отворен код, която се използва широко за уеб приложения.
- Firebase: Облачна платформа, която предоставя база данни в реално време и други услуги.
- FaunaDB: Безсървърна база данни, предназначена за глобални приложения.
Ето пример как да се свържете с база данни MongoDB в API маршрут на Next.js:
// pages/api/mongodb.js
import { MongoClient } from 'mongodb'
const uri = process.env.MONGODB_URI
const options = {}
let client
let clientPromise
if (!process.env.MONGODB_URI) {
throw new Error('Моля, добавете вашия Mongo URI в .env.local')
}
if (process.env.NODE_ENV === 'development') {
// В режим на разработка използвайте глобална променлива, така че стойността
// да се запази при презареждане на модули, причинено от HMR (Hot Module Replacement).
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options)
global._mongoClientPromise = client.connect()
}
clientPromise = global._mongoClientPromise
} else {
// В производствен режим е най-добре да не се използва глобална променлива.
client = new MongoClient(uri, options)
clientPromise = client.connect()
}
// Експортирайте MongoClient promise с обхват на модула. Като направите това в
// отделен модул, клиентът може безопасно да се използва повторно в множество
// функции. Вижте: https://github.com/vercel/next.js/blob/canary/examples/with-mongodb/lib/mongodb.js
export default async function handler(req, res) {
try {
const client = await clientPromise
const db = client.db(process.env.MONGODB_DB)
const collection = db.collection('users')
const users = await collection.find({}).toArray()
res.status(200).json({ users })
} catch (e) {
console.error(e)
res.status(500).json({ message: 'Неуспешно извличане на потребители' })
}
}
Преди да стартирате този код, уверете се, че имате инсталиран пакета mongodb
:
npm install mongodb
Трябва също така да зададете променливите на средата MONGODB_URI
и MONGODB_DB
. Тези променливи трябва да бъдат дефинирани във вашия файл .env.local
(или в настройките за променливи на средата на вашия хостинг доставчик за производство). MONGODB_URI
съдържа низа за връзка (connection string) към вашата MongoDB база данни, а MONGODB_DB
указва името на базата данни.
Удостоверяване и оторизация
Защитата на вашите API маршрути е от решаващо значение за сигурността. Next.js API Routes могат да бъдат защитени с помощта на различни техники за удостоверяване и оторизация, включително:
- JSON уеб токени (JWT): Стандарт за сигурно предаване на информация между страните като JSON обект.
- API ключове: Прост начин за ограничаване на достъпа до вашите API ендпойнти.
- OAuth: Протокол за делегиране, който позволява на потребителите да предоставят на приложения на трети страни достъп до своите ресурси, без да споделят своите идентификационни данни.
- NextAuth.js: Цялостно решение за удостоверяване с отворен код за Next.js приложения.
Ето пример как да защитите API маршрут, използвайки JWT удостоверяване:
// pages/api/protected.js
import jwt from 'jsonwebtoken'
const secret = process.env.JWT_SECRET
export default function handler(req, res) {
const token = req.headers.authorization?.split(' ')[1]
if (!token) {
return res.status(401).json({ message: 'Неупълномощен достъп' })
}
try {
const decoded = jwt.verify(token, secret)
// Обектът "decoded" съдържа потребителската информация, вградена в токена
// Например: const userId = decoded.userId;
// Продължаване на обработката на заявката
res.status(200).json({ message: 'Достъпът до защитения ресурс е успешен' })
} catch (error) {
return res.status(401).json({ message: 'Невалиден токен' })
}
}
Преди да стартирате този код, уверете се, че имате инсталиран пакета jsonwebtoken
:
npm install jsonwebtoken
Трябва също така да зададете променливата на средата JWT_SECRET
. Това трябва да бъде силен, произволно генериран таен ключ, който се използва за подписване и проверка на JWT. Съхранявайте го сигурно и никога не го излагайте във вашия клиентски код.
Мидълуер (Middleware)
Въпреки че Next.js не предлага традиционен мидълуер за API маршрути по същия начин като Express.js, можете да постигнете подобна функционалност, като обвиете вашите handler-и на API маршрути с функции за многократна употреба. Това ви позволява да изпълнявате задачи като:
- Удостоверяване: Проверка на потребителските идентификационни данни преди разрешаване на достъп до API ендпойнти.
- Оторизация: Проверка дали потребителят има необходимите разрешения за извършване на определено действие.
- Регистриране (Logging): Записване на входящи заявки и изходящи отговори за целите на одит и отстраняване на грешки.
- Валидация: Валидиране на данните от заявката, за да се гарантира, че отговарят на определени критерии.
- Ограничаване на честотата на заявките (Rate Limiting): Защита на вашето API от злоупотреби чрез ограничаване на броя на заявките, които потребителят може да направи в даден период от време.
Ето пример как да създадете прост мидълуер за регистриране:
// utils/middleware.js
export function withLogging(handler) {
return async function(req, res) {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`)
return handler(req, res)
}
}
За да използвате този мидълуер, просто обвийте вашия handler на API маршрута с функцията withLogging
:
// pages/api/logged.js
import { withLogging } from '../../utils/middleware'
async function handler(req, res) {
res.status(200).json({ message: 'Тази заявка беше регистрирана' })
}
export default withLogging(handler)
Добри практики за изграждане на Next.js API Routes
- Поддържайте вашите API маршрути малки и фокусирани. Всеки API маршрут трябва да обработва конкретна задача или ресурс.
- Използвайте променливи на средата за чувствителни данни. Никога не вграждайте тайни или API ключове в кода си.
- Валидирайте данните от заявката, за да предотвратите уязвимости в сигурността. Използвайте библиотека като Joi или Yup за валидиране на телата на заявките.
- Обработвайте грешките елегантно и предоставяйте информативни съобщения за грешки. Използвайте try-catch блокове и регистрирайте грешките на централно място.
- Използвайте кеширане, за да подобрите производителността. Кеширайте често достъпвани данни, за да намалите натоварването на базата данни.
- Наблюдавайте вашите API маршрути за производителност и грешки. Използвайте инструмент за наблюдение като Sentry или Datadog, за да следите здравето на вашето API.
- Документирайте вашите API маршрути с инструмент като Swagger или OpenAPI. Това улеснява други разработчици да използват вашето API.
- Обмислете използването на TypeScript за типова безопасност. TypeScript може да ви помогне да улавяте грешки по-рано и да подобрите поддръжката на вашия код.
- Мислете за интернационализацията (i18n) от самото начало. Ако вашето приложение ще се използва от потребители от различни държави, проектирайте вашите API маршрути така, че да поддържат множество езици и валути. Например, API ендпойнтите за електронна търговия може да се наложи да обработват различни данъчни ставки и разходи за доставка в зависимост от местоположението на потребителя.
- Приложете правилна CORS (Cross-Origin Resource Sharing) конфигурация. Това е от решаващо значение, когато до вашето API се осъществява достъп от домейн, различен от този на вашето Next.js приложение. Внимателно конфигурирайте CORS, за да разрешите достъп до вашите API ресурси само на оторизирани източници.
Напреднали техники
Фонови задачи
За дълготрайни задачи, които не трябва да блокират отговора на API, обмислете използването на фонови задачи. Можете да използвате библиотеки като BullMQ или Bree, за да управлявате вашите фонови задачи и да ги обработвате асинхронно.
WebSockets
За приложения в реално време можете да използвате WebSockets във вашите Next.js API маршрути. Библиотеки като Socket.IO и ws улесняват установяването на постоянни връзки между клиента и сървъра.
GraphQL
Ако се нуждаете от по-гъвкав и ефективен начин за извличане на данни, обмислете използването на GraphQL. Можете да използвате библиотеки като Apollo Server или Yoga, за да създадете GraphQL API ендпойнт във вашето Next.js приложение.
Заключение
Next.js API Routes предоставят мощен и удобен начин за изграждане на безсървърни бекенди директно във вашето Next.js приложение. Като се възползвате от предимствата на безсървърната архитектура, можете да опростите разработката, да подобрите производителността и да намалите разходите. Независимо дали изграждате проста форма за контакт или сложна платформа за електронна търговия, Next.js API Routes могат да ви помогнат да създадете стабилен и мащабируем бекенд с лекота. Със солидно разбиране на основите и прилагането на добри практики можете да използвате този мощен инструмент за създаване на ефективни, сигурни и глобално достъпни приложения.