Lær at skabe kraftfulde API-endepunkter med Next.js Route Handlers. Denne guide dækker alt fra grundlæggende opsætning til avancerede teknikker med praktiske eksempler og best practices.
Next.js Route Handlers: En Komplet Guide til Oprettelse af API-Endepunkter
Next.js har revolutioneret den måde, vi bygger webapplikationer på med sine kraftfulde funktioner som server-side rendering, statisk site-generering og nu, Route Handlers. Route Handlers giver en fleksibel og effektiv måde at oprette API-endepunkter direkte i din Next.js-applikation. Denne guide udforsker konceptet Route Handlers, deres fordele, og hvordan man effektivt bruger dem til at bygge robuste API'er.
Hvad er Next.js Route Handlers?
Route Handlers er funktioner, der er defineret i app
-mappen i et Next.js-projekt, og som håndterer indkommende HTTP-forespørgsler. I modsætning til den ældre pages/api
-tilgang (som bruger API Routes), tilbyder Route Handlers en mere strømlinet og fleksibel måde at definere API-endepunkter på sammen med dine React-komponenter. De er i bund og grund serverless funktioner, der udføres på edge-netværket eller i dit valgte servermiljø.
Tænk på Route Handlers som backend-logikken i din Next.js-applikation, der er ansvarlig for at behandle forespørgsler, interagere med databaser og returnere svar.
Fordele ved at Bruge Route Handlers
- Samlokalisering: Route Handlers ligger direkte ved siden af dine React-komponenter i
app
-mappen, hvilket fremmer bedre organisering og vedligeholdelse af koden. - TypeScript-understøttelse: Indbygget TypeScript-understøttelse sikrer typesikkerhed og en forbedret udvikleroplevelse.
- Middleware-integration: Integrer nemt middleware til opgaver som autentificering, autorisation og validering af forespørgsler.
- Streaming-understøttelse: Route Handlers kan streame data, hvilket gør det muligt at sende svar inkrementelt, hvilket er en fordel for store datasæt eller langvarige processer.
- Edge Functions: Implementer Route Handlers som Edge Functions for lav latenstid og svar tættere på dine brugere ved at udnytte globale CDN'er.
- Forenklet API-design: Route Handlers tilbyder en ren og intuitiv API til håndtering af forespørgsler og svar.
- Server Actions-integration: Tæt integration med Server Actions muliggør problemfri kommunikation mellem dine client-side komponenter og server-side logik.
Opsætning af dit Next.js-projekt
Før du dykker ned i Route Handlers, skal du sikre dig, at du har et Next.js-projekt opsat med app
-mappen. Hvis du starter et nyt projekt, skal du bruge følgende kommando:
npx create-next-app@latest my-nextjs-app
Vælg app
-mappen under opsætningsprocessen for at aktivere det nye routing-system.
Oprettelse af din Første Route Handler
Lad os oprette et simpelt API-endepunkt, der returnerer et JSON-svar. Opret en ny mappe i app
-mappen, for eksempel /app/api/hello
. I denne mappe skal du oprette en fil ved navn route.ts
(eller route.js
, hvis du ikke bruger TypeScript).
Her er koden til din første 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!' });
}
Forklaring:
import { NextResponse } from 'next/server';
: ImportererNextResponse
-objektet, som bruges til at konstruere API-svar.export async function GET(request: Request) { ... }
: Definerer en asynkron funktion, der håndterer GET-forespørgsler til/api/hello
-endepunktet.request
-parameteren giver adgang til det indkommende forespørgselsobjekt.return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
: Opretter et JSON-svar med en besked og returnerer det ved hjælp afNextResponse.json()
.
Nu kan du tilgå dette endepunkt ved at navigere til /api/hello
i din browser eller ved at bruge et værktøj som curl
eller Postman
.
Håndtering af Forskellige HTTP-Metoder
Route Handlers understøtter forskellige HTTP-metoder som GET, POST, PUT, DELETE, PATCH og OPTIONS. Du kan definere separate funktioner for hver metode i den samme route.ts
-fil.
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Logik til at hente alle brugere fra databasen
const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Eksempeldata
return NextResponse.json(users);
}
export async function POST(request: Request) {
const data = await request.json(); // Parse forespørgslens body som JSON
// Logik til at oprette en ny bruger i databasen ved hjælp af 'data'
const newUser = { id: 3, name: data.name, email: data.email }; // Eksempel
return NextResponse.json(newUser, { status: 201 }); // Returner den nye bruger med en 201 Created statuskode
}
Forklaring:
GET
-funktionen henter en liste over brugere (simuleret her) og returnerer dem som et JSON-svar.POST
-funktionen parser forespørgslens body som JSON, opretter en ny bruger (simuleret) og returnerer den nye bruger med en 201 Created statuskode.
Adgang til Forespørgselsdata
request
-objektet giver adgang til forskellige oplysninger om den indkommende forespørgsel, herunder headers, query-parametre og request body.
Headers
Du kan få adgang til request headers ved hjælp af request.headers
-egenskaben:
export async function GET(request: Request) {
const userAgent = request.headers.get('user-agent');
console.log('User Agent:', userAgent);
return NextResponse.json({ userAgent });
}
Query-parametre
For at få adgang til query-parametre kan du bruge URL
-konstruktøren:
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
For POST-, PUT- og PATCH-forespørgsler kan du få adgang til request body ved hjælp af metoderne request.json()
eller request.text()
, afhængigt af content-typen.
export async function POST(request: Request) {
const data = await request.json();
console.log('Data:', data);
return NextResponse.json({ receivedData: data });
}
Returnering af Svar
NextResponse
-objektet bruges til at konstruere API-svar. Det tilbyder flere metoder til at indstille headers, statuskoder og svar-bodies.
JSON-svar
Brug NextResponse.json()
-metoden til at returnere JSON-svar:
return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });
Tekstsvar
Brug new Response()
-konstruktøren til at returnere rene tekstsvar:
return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });
Omdirigeringer
Brug NextResponse.redirect()
til at omdirigere brugere til en anden 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));
}
Indstilling af Headers
Du kan indstille brugerdefinerede headers ved hjælp af headers
-optionen i NextResponse.json()
eller new Response()
:
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });
Middleware-integration
Middleware giver dig mulighed for at køre kode, før en forespørgsel håndteres af din Route Handler. Dette er nyttigt til autentificering, autorisation, logning og andre tværgående anliggender.
For at oprette middleware skal du oprette en fil ved navn middleware.ts
(eller middleware.js
) i app
-mappen eller en undermappe. Middlewaren vil gælde for alle ruter i den pågældende mappe og dens undermapper.
// 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*'], // Anvend denne middleware på stier, der starter med /protected/
};
Forklaring:
middleware
-funktionen tjekker for et autentificeringstoken i forespørgslens cookies.- Hvis tokenet mangler, omdirigeres brugeren til login-siden.
- Ellers tillader den, at forespørgslen fortsætter til Route Handler.
config
-objektet specificerer, at denne middleware kun skal anvendes på ruter, der starter med/protected/
.
Fejlhåndtering
Korrekt fejlhåndtering er afgørende for at bygge robuste API'er. Du kan bruge try...catch
-blokke til at håndtere undtagelser og returnere passende fejlsvar.
export async function GET(request: Request) {
try {
// Simuler en fejl
throw new Error('Something went wrong!');
} catch (error: any) {
console.error('Error:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Forklaring:
try...catch
-blokken fanger eventuelle undtagelser, der opstår i Route Handler.- I
catch
-blokken logges fejlen, og der returneres et fejlsvar med en 500 Internal Server Error statuskode.
Streaming af Svar
Route Handlers understøtter streaming af svar, hvilket giver dig mulighed for at sende data inkrementelt til klienten. Dette er især nyttigt for store datasæt eller langvarige processer.
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)); // Simuler forsinkelse
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' },
});
}
Forklaring:
generateData
-funktionen er en asynkron generator, der yielder datastykker med en forsinkelse.Readable.from()
-metoden opretter en læsbar strøm fra generatoren.Response
-objektet oprettes med den læsbare strøm som body, ogContent-Type
-headeren sættes tiltext/plain
.
Autentificering og Autorisation
At sikre dine API-endepunkter er afgørende. Du kan implementere autentificering og autorisation ved hjælp af middleware eller direkte i dine Route Handlers.
Autentificering
Autentificering verificerer identiteten af den bruger, der sender forespørgslen. Almindelige autentificeringsmetoder inkluderer:
- JWT (JSON Web Tokens): Generer et token ved succesfuldt login og verificer det ved efterfølgende forespørgsler.
- Sessionsbaseret autentificering: Brug cookies til at gemme sessionsidentifikatorer og verificer dem ved hver forespørgsel.
- OAuth: Deleger autentificering til en tredjepartsudbyder som Google eller Facebook.
Her er et eksempel på JWT-autentificering ved hjælp af 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'; // Erstat med en stærk, tilfældigt genereret hemmelighed
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.json({ message: 'Authentication required' }, { status: 401 });
}
try {
jwt.verify(token, secret);
return NextResponse.next();
} catch (error) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
}
}
export const config = {
matcher: ['/api/protected/:path*'],
};
Autorisation
Autorisation bestemmer, hvilke ressourcer en bruger har adgang til. Dette er typisk baseret på roller eller tilladelser.
Du kan implementere autorisation i dine Route Handlers ved at tjekke brugerens roller eller tilladelser og returnere en fejl, hvis de ikke har adgang.
// app/api/admin/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Antag, at du har en funktion til at hente brugerens rolle fra tokenet eller sessionen
const userRole = await getUserRole(request);
if (userRole !== 'admin') {
return NextResponse.json({ message: 'Unauthorized' }, { status: 403 });
}
// Logik til at hente admin-data
const adminData = { message: 'Admin data' };
return NextResponse.json(adminData);
}
async function getUserRole(request: Request): Promise {
// Erstat med din faktiske logik til at udtrække brugerens rolle fra forespørgslen
// Dette kan involvere verificering af et JWT-token eller tjek af en session
return 'admin'; // Eksempel: hårdkodet rolle til demonstration
}
Implementering af Route Handlers
Route Handlers implementeres som serverless funktioner hos din valgte hostingudbyder. Next.js understøtter forskellige implementeringsplatforme, herunder Vercel, Netlify, AWS og flere.
For Vercel er implementering så simpelt som at forbinde dit Git-repository til Vercel og pushe din kode. Vercel registrerer automatisk dit Next.js-projekt og implementerer dine Route Handlers som serverless funktioner.
Avancerede Teknikker
Edge Functions
Route Handlers kan implementeres som Edge Functions, som udføres på kanten af et CDN, tættere på dine brugere. Dette kan markant reducere latenstid og forbedre ydeevnen.
For at implementere en Route Handler som en Edge Function, skal du tilføje edge
-runtime til din route.ts
-fil:
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
Server Actions giver dig mulighed for at udføre server-side kode direkte fra dine React-komponenter. Route Handlers og Server Actions fungerer problemfrit sammen, hvilket gør det let at bygge komplekse applikationer.
Her er et eksempel på brug af en Server Action til at kalde en Route Handler:
// 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(); // Opdater siden for at afspejle ændringerne
}
}
export default function MyComponent() {
const router = useRouter();
return (
);
}
Caching
Caching kan markant forbedre ydeevnen af dine API-endepunkter. Du kan bruge Cache-Control
-headeren til at styre, hvordan dine svar caches af browsere og CDN'er.
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });
Dette eksempel indstiller Cache-Control
-headeren til public, max-age=3600
, hvilket fortæller browsere og CDN'er, at de skal cache svaret i en time.
Best Practices
- Brug TypeScript: Udnyt TypeScript's typesikkerhed til at forbedre kodekvaliteten og forhindre fejl.
- Valider Forespørgsler: Valider indkommende forespørgsler for at sikre dataintegritet og forhindre ondsindet input.
- Håndter Fejl Elegant: Implementer korrekt fejlhåndtering for at give informative fejlmeddelelser til klienter.
- Sikr Dine Endepunkter: Implementer autentificering og autorisation for at beskytte dine API-endepunkter.
- Brug Middleware: Brug middleware til tværgående anliggender som autentificering, logning og validering af forespørgsler.
- Cache Svar: Brug caching til at forbedre ydeevnen af dine API-endepunkter.
- Overvåg Dine API'er: Overvåg dine API'er for hurtigt at identificere og løse problemer.
- Dokumenter Dine API'er: Dokumenter dine API'er for at gøre dem nemme at bruge for andre udviklere. Overvej at bruge værktøjer som Swagger/OpenAPI til API-dokumentation.
Eksempler fra den Virkelige Verden
Her er et par eksempler fra den virkelige verden på, hvordan Route Handlers kan bruges:
- E-handels-API: Opret API-endepunkter til håndtering af produkter, ordrer og brugere.
- Sociale Medier-API: Opret API-endepunkter til at poste tweets, følge brugere og hente tidslinjer.
- Content Management System (CMS) API: Opret API-endepunkter til håndtering af indhold, brugere og indstillinger.
- Dataanalyse-API: Opret API-endepunkter til at indsamle og analysere data. For eksempel kunne en Route Handler modtage data fra tracking-pixels på forskellige hjemmesider og aggregere informationen til rapportering.
Eksempel på international e-handel: En Route Handler, der bruges til at hente produktpriser baseret på brugerens land. Endepunktet kunne bruge forespørgslens geolocation (afledt af IP-adresse) til at bestemme brugerens placering og returnere priser i den relevante valuta. Dette bidrager til en lokaliseret shoppingoplevelse.
Eksempel på global autentificering: En Route Handler, der implementerer multi-faktor-autentificering (MFA) for brugere verden over. Dette kunne involvere afsendelse af SMS-koder eller brug af authenticator-apps, alt imens forskellige regioners privatlivsregler og telekommunikationsinfrastrukturer respekteres.
Levering af flersproget indhold: En Route Handler, der leverer indhold på brugerens foretrukne sprog. Dette kan bestemmes ud fra Accept-Language
-headeren i forespørgslen. Dette eksempel fremhæver behovet for korrekt UTF-8-kodning og understøttelse af sprog, der læses fra højre mod venstre, hvor det er relevant.
Konklusion
Next.js Route Handlers tilbyder en kraftfuld og fleksibel måde at oprette API-endepunkter direkte i din Next.js-applikation. Ved at udnytte Route Handlers kan du nemt bygge robuste API'er, samlokalisere din backend-logik med dine React-komponenter og drage fordel af funktioner som middleware, streaming og Edge Functions.
Denne omfattende guide har dækket alt fra grundlæggende opsætning til avancerede teknikker. Ved at følge de bedste praksisser, der er beskrevet i denne guide, kan du bygge API'er af høj kvalitet, der er sikre, performante og vedligeholdelsesvenlige.