Български

Открийте Next.js API Routes и отключете full-stack възможности във вашите React приложения. Научете шаблони, добри практики и стратегии за внедряване.

Next.js API Routes: Шаблони за Full-Stack Разработка

Next.js революционизира React разработката, като предоставя стабилна рамка за изграждане на производителни и мащабируеми уеб приложения. Една от ключовите му характеристики са API Routes, които позволяват на разработчиците да създават бекенд функционалност директно в техните Next.js проекти. Този подход оптимизира разработката, опростява внедряването и отключва мощни full-stack възможности.

Какво представляват Next.js API Routes?

Next.js API Routes са serverless функции, написани директно в директорията /pages/api. Всеки файл в тази директория се превръща в API endpoint, който автоматично насочва HTTP заявки към съответната му функция. Това елиминира нуждата от отделен бекенд сървър, опростява архитектурата на приложението ви и намалява оперативните разходи.

Мислете за тях като за миниатюрни serverless функции, които живеят във вашето Next.js приложение. Те отговарят на HTTP заявки като GET, POST, PUT, DELETE и могат да взаимодействат с бази данни, външни API-та и други сървърни ресурси. От съществено значение е, че те се изпълняват само на сървъра, а не в браузъра на потребителя, което гарантира сигурността на чувствителни данни като API ключове.

Ключови ползи от API Routes

Първи стъпки с API Routes

Създаването на API route в Next.js е лесно. Просто създайте нов файл в директорията /pages/api. Името на файла ще определи пътя на маршрута. Например, създаването на файл на име /pages/api/hello.js ще създаде API endpoint, достъпен на /api/hello.

Пример: Просто API за поздрав

Ето един основен пример за API route, която връща JSON отговор:


// pages/api/hello.js

export default function handler(req, res) {
  res.status(200).json({ message: 'Здравей от Next.js API Route!' });
}

Този код дефинира асинхронна функция handler, която получава два аргумента:

Функцията задава HTTP статус код 200 (OK) и връща JSON отговор със съобщение.

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

Можете да обработвате различни HTTP методи (GET, POST, PUT, DELETE и др.) във вашата API route, като проверявате свойството req.method. Това ви позволява лесно да създавате RESTful API-та.


// pages/api/todos.js

export default async function handler(req, res) {
  if (req.method === 'GET') {
    // Извличане на всички задачи от базата данни
    const todos = await fetchTodos();
    res.status(200).json(todos);
  } else if (req.method === 'POST') {
    // Създаване на нова задача
    const newTodo = await createTodo(req.body);
    res.status(201).json(newTodo);
  } else {
    // Обработка на неподдържани методи
    res.status(405).json({ message: 'Методът не е позволен' });
  }
}

Този пример демонстрира как да обработвате GET и POST заявки за хипотетичен endpoint /api/todos. Той също така включва обработка на грешки за неподдържани методи.

Шаблони за Full-Stack Разработка с API Routes

Next.js API Routes позволяват различни full-stack шаблони за разработка. Ето някои често срещани случаи на употреба:

1. Извличане и манипулиране на данни

API Routes могат да се използват за извличане на данни от бази данни, външни API-та или други източници на данни. Те могат да се използват и за манипулиране на данни, като например създаване, актуализиране или изтриване на записи.

Пример: Извличане на потребителски данни от база данни


// pages/api/users/[id].js
import { query } from '../../../lib/db';

export default async function handler(req, res) {
  const { id } = req.query;

  try {
    const results = await query(
      'SELECT * FROM users WHERE id = ?',
      [id]
    );

    if (results.length === 0) {
      return res.status(404).json({ message: 'Потребителят не е намерен' });
    }

    res.status(200).json(results[0]);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Вътрешна грешка на сървъра' });
  }
}

Този пример извлича потребителски данни от база данни въз основа на ID на потребителя, предоставено в URL адреса. Той използва библиотека за заявки към база данни (предполагаема в lib/db) за взаимодействие с базата данни. Обърнете внимание на използването на параметризирани заявки за предотвратяване на SQL инжекции.

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

API Routes могат да се използват за имплементиране на логика за аутентификация и авторизация. Можете да ги използвате за проверка на потребителски идентификационни данни, генериране на JWT токени и защита на чувствителни ресурси.

Пример: Потребителска аутентификация


// pages/api/login.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { query } from '../../lib/db';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { email, password } = req.body;

    try {
      const results = await query(
        'SELECT * FROM users WHERE email = ?',
        [email]
      );

      if (results.length === 0) {
        return res.status(401).json({ message: 'Невалидни идентификационни данни' });
      }

      const user = results[0];

      const passwordMatch = await bcrypt.compare(password, user.password);

      if (!passwordMatch) {
        return res.status(401).json({ message: 'Невалидни идентификационни данни' });
      }

      const token = jwt.sign(
        { userId: user.id, email: user.email },
        process.env.JWT_SECRET,
        { expiresIn: '1h' }
      );

      res.status(200).json({ token });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Вътрешна грешка на сървъра' });
    }
  } else {
    res.status(405).json({ message: 'Методът не е позволен' });
  }
}

Този пример аутентифицира потребители, като сравнява предоставената парола със съхранената хеширана парола в базата данни. Ако идентификационните данни са валидни, той генерира JWT токен и го връща на клиента. След това клиентът може да използва този токен за аутентифициране на последващи заявки.

3. Обработка на форми и подаване на данни

API Routes могат да се използват за обработка на подадени форми и обработка на данни, изпратени от клиента. Това е полезно за създаване на контактни форми, регистрационни форми и други интерактивни елементи.

Пример: Подаване на контактна форма


// pages/api/contact.js
import { sendEmail } from '../../lib/email';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { name, email, message } = req.body;

    try {
      await sendEmail({
        to: 'admin@example.com',
        subject: 'Ново подаване на контактна форма',
        text: `Име: ${name}
Имейл: ${email}
Съобщение: ${message}`,
      });

      res.status(200).json({ message: 'Имейлът е изпратен успешно' });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Неуспешно изпращане на имейл' });
    }
  } else {
    res.status(405).json({ message: 'Методът не е позволен' });
  }
}

Този пример обработва подаването на контактна форма, като изпраща имейл до администратора. Той използва библиотека за изпращане на имейли (предполагаема в lib/email), за да изпрати имейла. Трябва да замените admin@example.com с действителния имейл адрес на получателя.

4. Webhooks и обработка на събития

API Routes могат да се използват за обработка на webhooks и отговор на събития от външни услуги. Това ви позволява да интегрирате вашето Next.js приложение с други платформи и да автоматизирате задачи.

Пример: Обработка на Stripe Webhook


// pages/api/stripe-webhook.js
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export const config = {
  api: {
    bodyParser: false, // Деактивиране на стандартното парсване на тялото
  },
};

async function buffer(req) {
  const chunks = [];
  for await (const chunk of req) {
    chunks.push(chunk);
  }
  return Buffer.concat(chunks).toString();
}

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const sig = req.headers['stripe-signature'];

    let event;

    try {
      const buf = await buffer(req);
      event = stripe.webhooks.constructEvent(buf, sig, process.env.STRIPE_WEBHOOK_SECRET);
    } catch (err) {
      console.log(`Грешка във Webhook: ${err.message}`);
      res.status(400).send(`Грешка във Webhook: ${err.message}`);
      return;
    }

    // Обработка на събитието
    switch (event.type) {
      case 'payment_intent.succeeded':
        const paymentIntent = event.data.object;
        console.log(`PaymentIntent за ${paymentIntent.amount} беше успешен!`);
        // След това дефинирайте и извикайте метод за обработка на успешния payment intent.
        // handlePaymentIntentSucceeded(paymentIntent);
        break;
      case 'payment_method.attached':
        const paymentMethod = event.data.object;
        // След това дефинирайте и извикайте метод за обработка на успешното прикачване на PaymentMethod.
        // handlePaymentMethodAttached(paymentMethod);
        break;
      default:
        // Неочакваван тип събитие
        console.log(`Необработен тип събитие ${event.type}.`);
    }

    // Връщане на 200 отговор за потвърждение за получаване на събитието
    res.status(200).json({ received: true });
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Методът не е позволен');
  }
}

Този пример обработва Stripe webhook, като проверява подписа и обработва данните от събитието. Той деактивира стандартното парсване на тялото и използва персонализирана буферна функция за четене на суровото тяло на заявката. Изключително важно е да деактивирате стандартното парсване на тялото, тъй като Stripe изисква суровото тяло за проверка на подписа. Не забравяйте да конфигурирате webhook endpoint-а си в таблото за управление на Stripe и да зададете променливата на средата STRIPE_WEBHOOK_SECRET.

Най-добри практики за API Routes

За да осигурите качеството и поддръжката на вашите API Routes, следвайте тези най-добри практики:

1. Модуларизирайте кода си

Избягвайте писането на големи, монолитни API routes. Вместо това, разделете кода си на по-малки, повторно използваеми модули. Това прави кода ви по-лесен за разбиране, тестване и поддръжка.

2. Имплементирайте обработка на грешки

Правилно обработвайте грешки във вашите API routes. Използвайте try...catch блокове, за да улавяте изключения и да връщате подходящи отговори за грешки на клиента. Записвайте грешките, за да подпомогнете отстраняването на грешки и наблюдението.

3. Валидирайте входните данни

Винаги валидирайте входните данни от клиента, за да предотвратите уязвимости в сигурността и да осигурите интегритет на данните. Използвайте библиотеки за валидация като Joi или Yup, за да дефинирате схеми за валидация и да налагате ограничения за данните.

4. Защитете чувствителни данни

Съхранявайте чувствителни данни, като API ключове и идентификационни данни за база данни, в променливи на средата. Никога не записвайте чувствителни данни в хранилището си за код.

5. Имплементирайте ограничение на заявките (Rate Limiting)

Защитете вашите API routes от злоупотреби, като имплементирате ограничение на заявките. Това ограничава броя на заявките, които клиент може да направи в рамките на определен период от време. Използвайте библиотеки за ограничение на заявките като express-rate-limit или limiter.

6. Защитете API ключовете

Не показвайте API ключове директно в клиентския код. Винаги насочвайте заявки през вашите API routes, за да защитите API ключовете си от неоторизиран достъп. Съхранявайте API ключовете сигурно в променливи на средата на вашия сървър.

7. Използвайте променливи на средата

Избягвайте твърдо кодиране на конфигурационни стойности в кода си. Вместо това, използвайте променливи на средата за съхранение на конфигурационни настройки. Това улеснява управлението на вашето приложение в различни среди (разработка, стейджинг, продукция).

8. Записване и наблюдение

Имплементирайте записване и наблюдение, за да следите производителността на вашите API routes. Записвайте важни събития, като грешки, предупреждения и успешни заявки. Използвайте инструменти за наблюдение, за да следите метрики като латентност на заявките, нива на грешки и използване на ресурси. Услуги като Sentry, Datadog или New Relic могат да бъдат полезни.

Съображения при внедряване

Next.js API Routes са проектирани да се внедряват на serverless платформи. Популярни опции за внедряване включват:

При внедряване на вашето Next.js приложение с API Routes, уверете се, че променливите на вашата среда са правилно конфигурирани на платформата за внедряване. Също така, вземете предвид времето за студено стартиране на serverless функциите, което може да повлияе на първоначалното време за отговор на вашите API routes. Оптимизирането на кода ви и използването на техники като provisioned concurrency могат да помогнат за смекчаване на проблемите със студеното стартиране.

Заключение

Next.js API Routes предоставят мощен и удобен начин за изграждане на full-stack приложения с React. Използвайки serverless функции, можете да опростите разработката, да намалите оперативните разходи и да подобрите производителността на приложението. Следвайки най-добрите практики, изложени в тази статия, можете да създавате стабилни и поддържани API Routes, които задвижват вашите Next.js приложения.

Независимо дали изграждате проста контактна форма или сложна платформа за електронна търговия, Next.js API Routes могат да ви помогнат да оптимизирате процеса на разработка и да предоставите изключителни потребителски изживявания.

Допълнително обучение