Русский

Узнайте, как использовать API-маршруты Next.js для создания бессерверных бэкендов прямо в вашем приложении Next.js. Это руководство охватывает всё: от базовой настройки до продвинутых техник.

API-маршруты Next.js: Простое создание бэкенда

Next.js произвел революцию во фронтенд-разработке благодаря своим мощным функциям и интуитивно понятной структуре. Но знаете ли вы, что он также может значительно упростить разработку бэкенда? API-маршруты Next.js позволяют создавать бессерверные конечные точки API прямо в вашем приложении Next.js, во многих случаях устраняя необходимость в отдельном бэкенд-сервере. Это всеобъемлющее руководство проведет вас через процесс создания надежного и масштабируемого бэкенда с использованием API-маршрутов Next.js.

Что такое API-маршруты Next.js?

API-маршруты — это бессерверные функции, которые вы создаете в каталоге /pages/api вашего проекта Next.js. Эти функции обрабатывают входящие HTTP-запросы и возвращают ответы, точно так же, как традиционный бэкенд-API. Ключевое отличие заключается в том, что они развертываются как бессерверные функции, что означает, что вам не нужно управлять серверами или инфраструктурой.

Думайте о них как о легковесных бэкенд-функциях, работающих по требованию и легко интегрированных с вашим фронтендом на Next.js.

Преимущества использования API-маршрутов Next.js

Начало работы с API-маршрутами Next.js

Давайте создадим простой 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"}

Понимание обработчика API-маршрута

Функция handler в вашем API-маршруте получает два аргумента:

Вы можете использовать эти объекты для обработки различных типов запросов, чтения данных из тела запроса, установки заголовков ответа и отправки различных типов ответов.

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

Вы можете использовать свойство req.method для определения HTTP-метода входящего запроса и соответствующей обработки различных методов. Например:

// pages/api/method.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    // Обработка GET-запроса
    res.status(200).json({ message: 'This is a GET request' })
  } else if (req.method === 'POST') {
    // Обработка POST-запроса
    res.status(200).json({ message: 'This is a POST request' })
  } else {
    // Обработка других методов
    res.status(405).json({ message: 'Method Not Allowed' })
  }
}

В этом примере API-маршрут обрабатывает как GET, так и POST запросы. Если метод запроса — GET, он отвечает JSON-объектом с сообщением "This is a GET request". Если метод запроса — POST, он отвечает JSON-объектом с сообщением "This is a POST request". Если метод запроса — любой другой, он отвечает ошибкой 405 Method Not Allowed.

Чтение данных из тела запроса

Для запросов POST, PUT и PATCH часто требуется читать данные из тела запроса. Next.js предоставляет встроенную поддержку для парсинга JSON и URL-encoded тел запросов. Чтобы разобрать тело 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:', name)
    console.log('Email:', email)

    res.status(200).json({ message: 'Data received successfully' })
  } else {
    res.status(405).json({ message: 'Method Not Allowed' })
  }
}

Чтобы протестировать этот 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('Something went wrong')
  } catch (error) {
    console.error(error)
    res.status(500).json({ message: 'Internal Server Error' })
  }
}

В этом примере API-маршрут имитирует ошибку, выбрасывая новый объект Error. Блок catch перехватывает ошибку, логирует ее в консоль и отправляет клиенту ответ 500 Internal Server Error. Для производственных сред рассмотрите использование надежной системы логирования, такой как Sentry или Datadog.

Подключение к базе данных

Один из самых распространенных сценариев использования API-маршрутов — это подключение к базе данных. API-маршруты Next.js легко интегрируются с различными базами данных, включая:

Вот пример того, как подключиться к базе данных 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('Please add your Mongo URI to .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 с областью видимости модуля. Делая это в
// отдельном модуле, клиент можно безопасно использовать повторно в нескольких
// функциях. См.: 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: 'Failed to fetch users' })
  }
}

Перед запуском этого кода убедитесь, что у вас установлен пакет mongodb:

npm install mongodb

Вам также необходимо установить переменные окружения MONGODB_URI и MONGODB_DB. Эти переменные должны быть определены в вашем файле .env.local (или в настройках переменных окружения вашего хостинг-провайдера для продакшена). MONGODB_URI содержит строку подключения к вашей базе данных MongoDB, а MONGODB_DB указывает имя базы данных.

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

Защита ваших API-маршрутов имеет решающее значение для безопасности. API-маршруты 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: 'Unauthorized' })
  }

  try {
    const decoded = jwt.verify(token, secret)
    // Объект "decoded" содержит информацию о пользователе, встроенную в токен
    // Например: const userId = decoded.userId;

    // Продолжение обработки запроса
    res.status(200).json({ message: 'Protected resource accessed successfully' })
  } catch (error) {
    return res.status(401).json({ message: 'Invalid token' })
  }
}

Перед запуском этого кода убедитесь, что у вас установлен пакет jsonwebtoken:

npm install jsonwebtoken

Вам также необходимо установить переменную окружения JWT_SECRET. Это должен быть сильный, случайно сгенерированный секретный ключ, который используется для подписи и проверки JWT. Храните его в безопасности и никогда не раскрывайте в клиентском коде.

Промежуточное ПО (Middleware)

Хотя Next.js не предлагает традиционное промежуточное ПО (middleware) для API-маршрутов так, как это делает Express.js, вы можете достичь аналогичной функциональности, оборачивая ваши обработчики 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)
  }
}

Чтобы использовать это промежуточное ПО, просто оберните ваш обработчик API-маршрута функцией withLogging:

// pages/api/logged.js
import { withLogging } from '../../utils/middleware'

async function handler(req, res) {
  res.status(200).json({ message: 'This request was logged' })
}

export default withLogging(handler)

Лучшие практики для создания API-маршрутов Next.js

Продвинутые техники

Фоновые задачи

Для длительных задач, которые не должны блокировать ответ API, рассмотрите использование фоновых задач. Вы можете использовать библиотеки, такие как BullMQ или Bree, для управления вашими фоновыми задачами и их асинхронной обработки.

WebSockets

Для приложений реального времени вы можете использовать WebSockets в ваших API-маршрутах Next.js. Библиотеки, такие как Socket.IO и ws, упрощают установление постоянных соединений между клиентом и сервером.

GraphQL

Если вам нужен более гибкий и эффективный способ получения данных, рассмотрите использование GraphQL. Вы можете использовать библиотеки, такие как Apollo Server или Yoga, для создания конечной точки GraphQL API в вашем приложении Next.js.

Заключение

API-маршруты Next.js предоставляют мощный и удобный способ создания бессерверных бэкендов прямо в вашем приложении Next.js. Используя преимущества бессерверной архитектуры, вы можете упростить разработку, повысить производительность и сократить затраты. Независимо от того, создаете ли вы простую контактную форму или сложную платформу для электронной коммерции, API-маршруты Next.js помогут вам с легкостью создать надежный и масштабируемый бэкенд. Обладая твердым пониманием основ и применяя лучшие практики, вы сможете использовать этот мощный инструмент для создания эффективных, безопасных и глобально доступных приложений.