Українська

Дізнайтеся, як використовувати 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: 'Це 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 Метод не дозволено.

Читання даних з тіла запиту

Для запитів 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: 'Дані успішно отримано' })
  } else {
    res.status(405).json({ message: 'Метод не дозволено' })
  }
}

Щоб протестувати цей API-маршрут, ви можете використати інструмент, такий як Postman або curl, щоб надіслати POST-запит з тілом у форматі JSON:

curl -X POST -H "Content-Type: application/json" -d '{"name": "Олена Петренко", "email": "olena.petrenko@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: 'Привіт, світе!' })
}

У цьому прикладі 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. Для виробничих середовищ розгляньте можливість використання надійної системи логування, такої як 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('Будь ласка, додайте ваш 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 на рівні модуля. Роблячи це в
// окремому модулі, клієнт можна безпечно використовувати повторно в кількох
// функціях. Див.: 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 містить рядок підключення до вашої бази даних 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: 'Не авторизовано' })
  }

  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 не пропонує традиційне проміжне програмне забезпечення (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: 'Цей запит було залоговано' })
}

export default withLogging(handler)

Найкращі практики для створення API-маршрутів Next.js

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

Фонові завдання

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

Вебсокети

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

GraphQL

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

Висновок

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