Leer hoe u krachtige API-eindpunten kunt creëren met Next.js Route Handlers. Deze gids behandelt alles, van de basisinstallatie tot geavanceerde technieken, met praktische voorbeelden en best practices.
Next.js Route Handlers: Een Uitgebreide Gids voor het Creëren van API-Eindpunten
Next.js heeft een revolutie teweeggebracht in de manier waarop we webapplicaties bouwen met zijn krachtige functies zoals server-side rendering, static site generation en nu, Route Handlers. Route Handlers bieden een flexibele en efficiënte manier om API-eindpunten direct binnen uw Next.js-applicatie te creëren. Deze gids verkent het concept van Route Handlers, hun voordelen en hoe u ze effectief kunt gebruiken om robuuste API's te bouwen.
Wat zijn Next.js Route Handlers?
Route Handlers zijn functies die binnen de app
-directory van een Next.js-project worden gedefinieerd en die inkomende HTTP-verzoeken afhandelen. In tegenstelling tot de oudere pages/api
-aanpak (die API Routes gebruikt), bieden Route Handlers een meer gestroomlijnde en flexibele manier om API-eindpunten te definiëren naast uw React-componenten. Ze zijn in wezen serverless functies die worden uitgevoerd op de edge of in uw gekozen serveromgeving.
Zie Route Handlers als de backend-logica van uw Next.js-applicatie, verantwoordelijk voor het verwerken van verzoeken, de interactie met databases en het terugsturen van antwoorden.
Voordelen van het Gebruik van Route Handlers
- Colocatie: Route Handlers bevinden zich direct naast uw React-componenten in de
app
-directory, wat een betere organisatie en onderhoudbaarheid van de code bevordert. - TypeScript-ondersteuning: Ingebouwde TypeScript-ondersteuning zorgt voor typeveiligheid en een verbeterde ontwikkelaarservaring.
- Middleware-integratie: Integreer eenvoudig middleware voor taken zoals authenticatie, autorisatie en verzoekvalidatie.
- Streaming-ondersteuning: Route Handlers kunnen data streamen, waardoor u antwoorden stapsgewijs kunt verzenden, wat voordelig is voor grote datasets of langdurige processen.
- Edge Functions: Implementeer Route Handlers als Edge Functions voor lage latentie-antwoorden dichter bij uw gebruikers, gebruikmakend van wereldwijde CDN's.
- Vereenvoudigd API-ontwerp: Route Handlers bieden een schone en intuïtieve API voor het afhandelen van verzoeken en antwoorden.
- Integratie met Server Actions: Nauwe integratie met Server Actions maakt naadloze communicatie mogelijk tussen uw client-side componenten en server-side logica.
Uw Next.js-project opzetten
Voordat u in Route Handlers duikt, zorg ervoor dat u een Next.js-project hebt opgezet met de app
-directory. Als u een nieuw project start, gebruik dan het volgende commando:
npx create-next-app@latest my-nextjs-app
Kies de app
-directory tijdens het installatieproces om het nieuwe routingsysteem in te schakelen.
Uw Eerste Route Handler Maken
Laten we een eenvoudig API-eindpunt maken dat een JSON-respons retourneert. Maak een nieuwe directory binnen de app
-directory, bijvoorbeeld /app/api/hello
. Maak in deze directory een bestand aan met de naam route.ts
(of route.js
als u geen TypeScript gebruikt).
Hier is de code voor uw eerste Route Handler:
// app/api/hello/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
}
Uitleg:
import { NextResponse } from 'next/server';
: Importeert hetNextResponse
-object, dat wordt gebruikt om API-antwoorden samen te stellen.export async function GET(request: Request) { ... }
: Definieert een asynchrone functie die GET-verzoeken naar het/api/hello
-eindpunt afhandelt. Derequest
-parameter geeft toegang tot het inkomende verzoekobject.return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
: Creëert een JSON-respons met een bericht en retourneert deze met behulp vanNextResponse.json()
.
Nu kunt u dit eindpunt benaderen door naar /api/hello
te navigeren in uw browser of door een tool zoals curl
of Postman
te gebruiken.
Verschillende HTTP-methoden afhandelen
Route Handlers ondersteunen verschillende HTTP-methoden zoals GET, POST, PUT, DELETE, PATCH en OPTIONS. U kunt voor elke methode afzonderlijke functies definiëren binnen hetzelfde route.ts
-bestand.
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Logica om alle gebruikers uit de database op te halen
const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Voorbeelddata
return NextResponse.json(users);
}
export async function POST(request: Request) {
const data = await request.json(); // Parse de request body als JSON
// Logica om een nieuwe gebruiker in de database aan te maken met 'data'
const newUser = { id: 3, name: data.name, email: data.email }; // Voorbeeld
return NextResponse.json(newUser, { status: 201 }); // Retourneer de nieuwe gebruiker met een 201 Created-statuscode
}
Uitleg:
- De
GET
-functie haalt een lijst met gebruikers op (hier gesimuleerd) en retourneert deze als een JSON-respons. - De
POST
-functie parseert de request body als JSON, maakt een nieuwe gebruiker aan (gesimuleerd) en retourneert de nieuwe gebruiker met een 201 Created-statuscode.
Toegang tot Verzoekgegevens
Het request
-object biedt toegang tot diverse informatie over het inkomende verzoek, inclusief headers, queryparameters en de request body.
Headers
U kunt request headers benaderen via de request.headers
-eigenschap:
export async function GET(request: Request) {
const userAgent = request.headers.get('user-agent');
console.log('User Agent:', userAgent);
return NextResponse.json({ userAgent });
}
Queryparameters
Om queryparameters te benaderen, kunt u de URL
-constructor gebruiken:
export async function GET(request: Request) {
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
const id = searchParams.get('id');
console.log('ID:', id);
return NextResponse.json({ id });
}
Request Body
Voor POST-, PUT- en PATCH-verzoeken kunt u de request body benaderen met de methoden request.json()
of request.text()
, afhankelijk van het contenttype.
export async function POST(request: Request) {
const data = await request.json();
console.log('Data:', data);
return NextResponse.json({ receivedData: data });
}
Antwoorden Retourneren
Het NextResponse
-object wordt gebruikt om API-antwoorden samen te stellen. Het biedt verschillende methoden voor het instellen van headers, statuscodes en response bodies.
JSON-antwoorden
Gebruik de NextResponse.json()
-methode om JSON-antwoorden te retourneren:
return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });
Tekstantwoorden
Gebruik de new Response()
-constructor om platte tekst-antwoorden te retourneren:
return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });
Omleidingen
Gebruik NextResponse.redirect()
om gebruikers om te leiden naar een andere URL:
import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.redirect(new URL('/new-location', request.url));
}
Headers Instellen
U kunt aangepaste headers instellen met de headers
-optie in NextResponse.json()
of new Response()
:
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });
Middleware-integratie
Middleware stelt u in staat om code uit te voeren voordat een verzoek wordt afgehandeld door uw Route Handler. Dit is nuttig voor authenticatie, autorisatie, logging en andere doorsnijdende belangen.
Om middleware te maken, maakt u een bestand met de naam middleware.ts
(of middleware.js
) in de app
-directory of een submap. De middleware is van toepassing op alle routes binnen die directory en de bijbehorende submappen.
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/protected/:path*'], // Pas deze middleware toe op paden die beginnen met /protected/
};
Uitleg:
- De
middleware
-functie controleert op een authenticatietoken in de request cookies. - Als het token ontbreekt, leidt het de gebruiker om naar de inlogpagina.
- Anders staat het toe dat het verzoek doorgaat naar de Route Handler.
- Het
config
-object specificeert dat deze middleware alleen van toepassing moet zijn op routes die beginnen met/protected/
.
Foutafhandeling
Goede foutafhandeling is cruciaal voor het bouwen van robuuste API's. U kunt try...catch
-blokken gebruiken om uitzonderingen af te handelen en passende foutreacties te retourneren.
export async function GET(request: Request) {
try {
// Simuleer een fout
throw new Error('Something went wrong!');
} catch (error: any) {
console.error('Error:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Uitleg:
- Het
try...catch
-blok vangt alle uitzonderingen op die zich binnen de Route Handler voordoen. - In het
catch
-blok wordt de fout gelogd en wordt een foutreactie geretourneerd met een 500 Internal Server Error-statuscode.
Streaming-antwoorden
Route Handlers ondersteunen streaming-antwoorden, waarmee u data stapsgewijs naar de client kunt sturen. Dit is met name handig voor grote datasets of langdurige processen.
import { Readable } from 'stream';
import { NextResponse } from 'next/server';
async function* generateData() {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Simuleer vertraging
yield `Data chunk ${i}\n`;
}
}
export async function GET(request: Request) {
const readableStream = Readable.from(generateData());
return new Response(readableStream, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
Uitleg:
- De
generateData
-functie is een asynchrone generator die datastukken met een vertraging oplevert. - De
Readable.from()
-methode creëert een leesbare stream van de generator. - Het
Response
-object wordt gemaakt met de leesbare stream als de body, en deContent-Type
-header wordt ingesteld optext/plain
.
Authenticatie en Autorisatie
Het beveiligen van uw API-eindpunten is cruciaal. U kunt authenticatie en autorisatie implementeren met behulp van middleware of rechtstreeks binnen uw Route Handlers.
Authenticatie
Authenticatie verifieert de identiteit van de gebruiker die het verzoek doet. Gangbare authenticatiemethoden zijn onder meer:
- JWT (JSON Web Tokens): Genereer een token bij succesvol inloggen en verifieer deze bij volgende verzoeken.
- Sessiegebaseerde Authenticatie: Gebruik cookies om sessie-ID's op te slaan en verifieer ze bij elk verzoek.
- OAuth: Delegeer authenticatie aan een externe provider zoals Google of Facebook.
Hier is een voorbeeld van JWT-authenticatie met behulp van middleware:
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';
const secret = process.env.JWT_SECRET || 'your-secret-key'; // Vervang door een sterk, willekeurig gegenereerd geheim
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.json({ message: 'Authenticatie vereist' }, { status: 401 });
}
try {
jwt.verify(token, secret);
return NextResponse.next();
} catch (error) {
return NextResponse.json({ message: 'Ongeldig token' }, { status: 401 });
}
}
export const config = {
matcher: ['/api/protected/:path*'],
};
Autorisatie
Autorisatie bepaalt tot welke bronnen een gebruiker toegang heeft. Dit is doorgaans gebaseerd op rollen of permissies.
U kunt autorisatie implementeren binnen uw Route Handlers door de rollen of permissies van de gebruiker te controleren en een fout terug te geven als ze geen toegang hebben.
// app/api/admin/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Neem aan dat u een functie hebt om de rol van de gebruiker op te halen uit het token of de sessie
const userRole = await getUserRole(request);
if (userRole !== 'admin') {
return NextResponse.json({ message: 'Ongeautoriseerd' }, { status: 403 });
}
// Logica om admin-gegevens op te halen
const adminData = { message: 'Admin data' };
return NextResponse.json(adminData);
}
async function getUserRole(request: Request): Promise {
// Vervang dit door uw eigenlijke logica om de rol van de gebruiker uit het verzoek te extraheren
// Dit kan het verifiëren van een JWT-token of het controleren van een sessie inhouden
return 'admin'; // Voorbeeld: hardgecodeerde rol voor demonstratiedoeleinden
}
Route Handlers Implementeren
Route Handlers worden geïmplementeerd als serverless functies bij uw gekozen hostingprovider. Next.js ondersteunt verschillende implementatieplatforms, waaronder Vercel, Netlify, AWS en meer.
Voor Vercel is de implementatie zo eenvoudig als het verbinden van uw Git-repository met Vercel en het pushen van uw code. Vercel detecteert automatisch uw Next.js-project en implementeert uw Route Handlers als serverless functies.
Geavanceerde Technieken
Edge Functions
Route Handlers kunnen worden geïmplementeerd als Edge Functions, die worden uitgevoerd aan de rand van een CDN, dichter bij uw gebruikers. Dit kan de latentie aanzienlijk verminderen en de prestaties verbeteren.
Om een Route Handler als Edge Function te implementeren, voegt u de edge
-runtime toe aan uw route.ts
-bestand:
export const runtime = 'edge';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from the Edge!' });
}
Server Actions
Met Server Actions kunt u server-side code rechtstreeks vanuit uw React-componenten uitvoeren. Route Handlers en Server Actions werken naadloos samen, waardoor u gemakkelijk complexe applicaties kunt bouwen.
Hier is een voorbeeld van het gebruik van een Server Action om een Route Handler aan te roepen:
// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
async function handleSubmit(data: FormData) {
'use server';
const name = data.get('name');
const email = data.get('email');
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ name, email }),
});
if (response.ok) {
router.refresh(); // Ververs de pagina om de wijzigingen weer te geven
}
}
export default function MyComponent() {
const router = useRouter();
return (
);
}
Caching
Caching kan de prestaties van uw API-eindpunten aanzienlijk verbeteren. U kunt de Cache-Control
-header gebruiken om te bepalen hoe uw antwoorden worden gecachet door browsers en CDN's.
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });
Dit voorbeeld stelt de Cache-Control
-header in op public, max-age=3600
, wat browsers en CDN's vertelt om het antwoord een uur lang te cachen.
Best Practices
- Gebruik TypeScript: Maak gebruik van de typeveiligheid van TypeScript om de codekwaliteit te verbeteren en fouten te voorkomen.
- Valideer Verzoeken: Valideer inkomende verzoeken om de data-integriteit te waarborgen en kwaadaardige invoer te voorkomen.
- Handel Fouten Correct Af: Implementeer een goede foutafhandeling om informatieve foutmeldingen aan clients te geven.
- Beveilig Uw Eindpunten: Implementeer authenticatie en autorisatie om uw API-eindpunten te beschermen.
- Gebruik Middleware: Gebruik middleware voor doorsnijdende belangen zoals authenticatie, logging en verzoekvalidatie.
- Cache Antwoorden: Gebruik caching om de prestaties van uw API-eindpunten te verbeteren.
- Monitor Uw API's: Monitor uw API's om problemen snel te identificeren en op te lossen.
- Documenteer Uw API's: Documenteer uw API's om ze gebruiksvriendelijk te maken voor andere ontwikkelaars. Overweeg tools zoals Swagger/OpenAPI voor API-documentatie.
Praktijkvoorbeelden
Hier zijn enkele praktijkvoorbeelden van hoe Route Handlers kunnen worden gebruikt:
- E-commerce API: Creëer API-eindpunten voor het beheren van producten, bestellingen en gebruikers.
- Social Media API: Creëer API-eindpunten voor het plaatsen van tweets, het volgen van gebruikers en het ophalen van tijdlijnen.
- Content Management System (CMS) API: Creëer API-eindpunten voor het beheren van content, gebruikers en instellingen.
- Data-analyse API: Creëer API-eindpunten voor het verzamelen en analyseren van data. Een Route Handler kan bijvoorbeeld data ontvangen van trackingpixels op verschillende websites en de informatie samenvoegen voor rapportage.
Internationaal E-commerce voorbeeld: Een Route Handler die wordt gebruikt om productprijzen op te halen op basis van het land van de gebruiker. Het eindpunt kan de geolocatie van het verzoek (afgeleid van het IP-adres) gebruiken om de locatie van de gebruiker te bepalen en prijzen in de juiste valuta te retourneren. Dit draagt bij aan een gelokaliseerde winkelervaring.
Wereldwijd Authenticatievoorbeeld: Een Route Handler die multi-factor authenticatie (MFA) implementeert voor gebruikers wereldwijd. Dit kan het verzenden van sms-codes of het gebruik van authenticator-apps inhouden, met inachtneming van de privacyregelgeving en telecommunicatie-infrastructuren van verschillende regio's.
Meertalige Contentlevering: Een Route Handler die content levert in de voorkeurstaal van de gebruiker. Dit kan worden bepaald aan de hand van de `Accept-Language`-header in het verzoek. Dit voorbeeld benadrukt de noodzaak van correcte UTF-8-codering en ondersteuning voor rechts-naar-links talen waar van toepassing.
Conclusie
Next.js Route Handlers bieden een krachtige en flexibele manier om API-eindpunten direct binnen uw Next.js-applicatie te creëren. Door gebruik te maken van Route Handlers kunt u gemakkelijk robuuste API's bouwen, uw backend-logica coloceren met uw React-componenten en profiteren van functies zoals middleware, streaming en Edge Functions.
Deze uitgebreide gids heeft alles behandeld, van de basisinstallatie tot geavanceerde technieken. Door de best practices in deze gids te volgen, kunt u hoogwaardige API's bouwen die veilig, performant en onderhoudbaar zijn.