Nederlands

Verken Next.js API Routes en ontgrendel full-stack ontwikkelmogelijkheden binnen uw React-applicaties. Leer patronen, best practices en implementatiestrategieën.

Next.js API Routes: Full-Stack Ontwikkelpatronen

Next.js heeft een revolutie teweeggebracht in React-ontwikkeling door een robuust framework te bieden voor het bouwen van performante en schaalbare webapplicaties. Een van de belangrijkste functies is API Routes, waarmee ontwikkelaars backend-functionaliteit rechtstreeks in hun Next.js-projecten kunnen creëren. Deze aanpak stroomlijnt de ontwikkeling, vereenvoudigt de implementatie en ontgrendelt krachtige full-stack mogelijkheden.

Wat zijn Next.js API Routes?

Next.js API Routes zijn serverloze functies die rechtstreeks in uw /pages/api directory worden geschreven. Elk bestand in deze directory wordt een API-endpoint, dat automatisch HTTP-verzoeken naar de bijbehorende functie routeert. Dit elimineert de noodzaak van een aparte backend-server, waardoor uw applicatiearchitectuur wordt vereenvoudigd en de operationele overhead wordt verminderd.

Beschouw ze als miniatuur serverloze functies die zich in uw Next.js-app bevinden. Ze reageren op HTTP-verzoeken zoals GET, POST, PUT, DELETE en kunnen communiceren met databases, externe API's en andere server-side resources. Cruciaal is dat ze alleen op de server worden uitgevoerd, niet in de browser van de gebruiker, waardoor de beveiliging van gevoelige gegevens zoals API-sleutels wordt gewaarborgd.

Belangrijkste Voordelen van API Routes

Aan de slag met API Routes

Het maken van een API-route in Next.js is eenvoudig. Maak gewoon een nieuw bestand in de /pages/api directory. De bestandsnaam bepaalt het pad van de route. Het maken van een bestand met de naam /pages/api/hello.js creëert bijvoorbeeld een API-endpoint dat toegankelijk is via /api/hello.

Voorbeeld: Een Eenvoudige Begroeting API

Hier is een basisvoorbeeld van een API-route die een JSON-respons retourneert:


// pages/api/hello.js

export default function handler(req, res) {
  res.status(200).json({ message: 'Hallo van Next.js API Route!' });
}

Deze code definieert een asynchrone functie handler die twee argumenten ontvangt:

De functie stelt de HTTP-statuscode in op 200 (OK) en retourneert een JSON-respons met een bericht.

Verschillende HTTP-methoden afhandelen

U kunt verschillende HTTP-methoden (GET, POST, PUT, DELETE, enz.) binnen uw API-route afhandelen door de eigenschap req.method te controleren. Hierdoor kunt u eenvoudig RESTful API's maken.


// pages/api/todos.js

export default async function handler(req, res) {
  if (req.method === 'GET') {
    // Haal alle todos op uit de database
    const todos = await fetchTodos();
    res.status(200).json(todos);
  } else if (req.method === 'POST') {
    // Maak een nieuwe todo
    const newTodo = await createTodo(req.body);
    res.status(201).json(newTodo);
  } else {
    // Ondersteunde methoden afhandelen
    res.status(405).json({ message: 'Methode niet toegestaan' });
  }
}

Dit voorbeeld laat zien hoe u GET- en POST-verzoeken voor een hypothetisch /api/todos endpoint kunt afhandelen. Het bevat ook foutafhandeling voor niet-ondersteunde methoden.

Full-Stack Ontwikkelpatronen met API Routes

Next.js API Routes maken verschillende full-stack ontwikkelpatronen mogelijk. Hier zijn enkele veelvoorkomende use-cases:

1. Data ophalen en manipuleren

API Routes kunnen worden gebruikt om gegevens op te halen uit databases, externe API's of andere gegevensbronnen. Ze kunnen ook worden gebruikt om gegevens te manipuleren, zoals het maken, bijwerken of verwijderen van records.

Voorbeeld: Gebruikersgegevens ophalen uit een Database


// 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: 'Gebruiker niet gevonden' });
    }

    res.status(200).json(results[0]);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Interne Serverfout' });
  }
}

Dit voorbeeld haalt gebruikersgegevens op uit een database op basis van de gebruikers-ID die in de URL is opgegeven. Het gebruikt een database query library (vermoedelijk in lib/db) om te communiceren met de database. Let op het gebruik van geparametriseerde queries om SQL-injectie kwetsbaarheden te voorkomen.

2. Authenticatie en Autorisatie

API Routes kunnen worden gebruikt om authenticatie- en autorisatielogica te implementeren. U kunt ze gebruiken om gebruikersgegevens te verifiëren, JWT-tokens te genereren en gevoelige resources te beschermen.

Voorbeeld: Gebruikersauthenticatie


// 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: 'Ongeldige inloggegevens' });
      }

      const user = results[0];

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

      if (!passwordMatch) {
        return res.status(401).json({ message: 'Ongeldige inloggegevens' });
      }

      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: 'Interne Serverfout' });
    }
  } else {
    res.status(405).json({ message: 'Methode niet toegestaan' });
  }
}

Dit voorbeeld authenticeert gebruikers door het opgegeven wachtwoord te vergelijken met het opgeslagen gehashte wachtwoord in de database. Als de inloggegevens geldig zijn, genereert het een JWT-token en retourneert het naar de client. De client kan dit token vervolgens gebruiken om volgende verzoeken te authenticeren.

3. Formulierafhandeling en Gegevensindiening

API Routes kunnen worden gebruikt om formulierinzendingen te verwerken en gegevens te verwerken die van de client zijn verzonden. Dit is handig voor het maken van contactformulieren, registratieformulieren en andere interactieve elementen.

Voorbeeld: Contactformulier Indienen


// 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: 'Nieuw Contactformulier Indienen',
        text: `Naam: ${name}\nEmail: ${email}\nBericht: ${message}`,
      });

      res.status(200).json({ message: 'E-mail succesvol verzonden' });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'E-mail verzenden mislukt' });
    }
  } else {
    res.status(405).json({ message: 'Methode niet toegestaan' });
  }
}

Dit voorbeeld behandelt een contactformulierinzending door een e-mail naar de beheerder te sturen. Het gebruikt een e-mail verzendbibliotheek (vermoedelijk in lib/email) om de e-mail te verzenden. U moet admin@example.com vervangen door het daadwerkelijke e-mailadres van de ontvanger.

4. Webhooks en Event Handling

API Routes kunnen worden gebruikt om webhooks af te handelen en te reageren op gebeurtenissen van externe services. Hierdoor kunt u uw Next.js-applicatie integreren met andere platforms en taken automatiseren.

Voorbeeld: Een Stripe Webhook Afhandelen


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

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

export const config = {
  api: {
    bodyParser: false, // Standaard body parsing uitschakelen
  },
};

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 Error: ${err.message}`);
      res.status(400).send(`Webhook Error: ${err.message}`);
      return;
    }

    // De gebeurtenis afhandelen
    switch (event.type) {
      case 'payment_intent.succeeded':
        const paymentIntent = event.data.object;
        console.log(`PaymentIntent voor ${paymentIntent.amount} was succesvol!`);
        // Definieer en roep vervolgens een methode aan om de succesvolle betaalintentie af te handelen.
        // handlePaymentIntentSucceeded(paymentIntent);
        break;
      case 'payment_method.attached':
        const paymentMethod = event.data.object;
        // Definieer en roep vervolgens een methode aan om de succesvolle koppeling van een PaymentMethod af te handelen.
        // handlePaymentMethodAttached(paymentMethod);
        break;
      default:
        // Onverwacht gebeurtenistype
        console.log(`Niet-afgehandeld gebeurtenistype ${event.type}.`);
    }

    // Retourneer een 200-reactie om ontvangst van de gebeurtenis te bevestigen
    res.status(200).json({ received: true });
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}

Dit voorbeeld behandelt een Stripe-webhook door de handtekening te verifiëren en de gebeurtenisgegevens te verwerken. Het schakelt de standaard body parser uit en gebruikt een aangepaste bufferfunctie om de onbewerkte request body te lezen. Het is cruciaal om de standaard body parser uit te schakelen omdat Stripe de onbewerkte body vereist voor handtekening verificatie. Vergeet niet om uw Stripe-webhook endpoint in uw Stripe-dashboard te configureren en de STRIPE_WEBHOOK_SECRET omgevingsvariabele in te stellen.

Best Practices voor API Routes

Om de kwaliteit en onderhoudbaarheid van uw API Routes te waarborgen, volgt u deze best practices:

1. Modulariseer uw code

Vermijd het schrijven van grote, monolithische API-routes. Verdeel in plaats daarvan uw code in kleinere, herbruikbare modules. Dit maakt uw code gemakkelijker te begrijpen, te testen en te onderhouden.

2. Implementeer Foutafhandeling

Behandel fouten correct in uw API-routes. Gebruik try...catch blokken om uitzonderingen op te vangen en passende foutreacties naar de client terug te sturen. Log fouten om te helpen bij het debuggen en monitoren.

3. Valideer Invoergegevens

Valideer altijd invoergegevens van de client om beveiligingslekken te voorkomen en de gegevensintegriteit te waarborgen. Gebruik validatiebibliotheken zoals Joi of Yup om validatieschema's te definiëren en gegevensbeperkingen af te dwingen.

4. Bescherm Gevoelige Gegevens

Sla gevoelige gegevens, zoals API-sleutels en database-inloggegevens, op in omgevingsvariabelen. Leg nooit gevoelige gegevens vast in uw code repository.

5. Implementeer Rate Limiting

Bescherm uw API-routes tegen misbruik door rate limiting te implementeren. Dit beperkt het aantal verzoeken dat een client binnen een bepaalde periode kan indienen. Gebruik rate limiting bibliotheken zoals express-rate-limit of limiter.

6. Beveilig API-sleutels

Stel API-sleutels niet rechtstreeks bloot in client-side code. Proxy verzoeken altijd via uw API-routes om uw API-sleutels te beschermen tegen ongeautoriseerde toegang. Sla API-sleutels veilig op in omgevingsvariabelen op uw server.

7. Gebruik Omgevingsvariabelen

Vermijd het hardcoderen van configuratiewaarden in uw code. Gebruik in plaats daarvan omgevingsvariabelen om configuratie-instellingen op te slaan. Dit maakt het gemakkelijker om uw applicatie in verschillende omgevingen (ontwikkeling, staging, productie) te beheren.

8. Logging en Monitoring

Implementeer logging en monitoring om de prestaties van uw API-routes te volgen. Log belangrijke gebeurtenissen, zoals fouten, waarschuwingen en succesvolle verzoeken. Gebruik monitoringtools om statistieken te volgen, zoals request latency, foutpercentages en resourcegebruik. Services zoals Sentry, Datadog of New Relic kunnen nuttig zijn.

Implementatieoverwegingen

Next.js API Routes zijn ontworpen om te worden geïmplementeerd op serverloze platforms. Populaire implementatieopties zijn:

Wanneer u uw Next.js-applicatie met API Routes implementeert, moet u ervoor zorgen dat uw omgevingsvariabelen correct zijn geconfigureerd op het implementatieplatform. Overweeg ook de cold start-tijd van serverloze functies, die de initiële responstijd van uw API-routes kunnen beïnvloeden. Het optimaliseren van uw code en het gebruik van technieken zoals provisioned concurrency kan helpen bij het verminderen van cold start-problemen.

Conclusie

Next.js API Routes bieden een krachtige en handige manier om full-stack applicaties te bouwen met React. Door gebruik te maken van serverloze functies, kunt u de ontwikkeling vereenvoudigen, de operationele overhead verminderen en de applicatieprestaties verbeteren. Door de best practices te volgen die in dit artikel worden beschreven, kunt u robuuste en onderhoudbare API Routes maken die uw Next.js-applicaties aandrijven.

Of u nu een eenvoudig contactformulier of een complex e-commerceplatform bouwt, Next.js API Routes kunnen u helpen uw ontwikkelingsproces te stroomlijnen en uitzonderlijke gebruikerservaringen te leveren.

Verder Leren