Dansk

Udforsk Next.js middleware, en kraftfuld funktion til at opsnappe og modificere indkommende anmodninger. Lær at implementere godkendelse, autorisation, omdirigering og A/B-testning med praktiske eksempler.

Next.js Middleware: Mestring af Anmodningsopsnapning for Dynamiske Applikationer

Next.js middleware tilbyder en fleksibel og kraftfuld måde at opsnappe og modificere indkommende anmodninger, før de når dine ruter. Denne kapacitet gør det muligt for dig at implementere en bred vifte af funktioner, fra godkendelse og autorisation til omdirigering og A/B-testning, alt imens ydeevnen optimeres. Denne omfattende guide vil gennemgå de grundlæggende koncepter i Next.js middleware og demonstrere, hvordan du kan udnytte det effektivt.

Hvad er Next.js Middleware?

Middleware i Next.js er en funktion, der kører, før en anmodning er fuldført. Det giver dig mulighed for at:

Middleware-funktioner defineres i middleware.ts (eller middleware.js) filen i roden af dit projekt. De udføres for hver rute i din applikation eller for specifikke ruter baseret på konfigurerbare matchers.

Nøglekoncepter og Fordele

Request-objekt

request-objektet giver adgang til information om den indkommende anmodning, herunder:

Response-objekt

Middleware-funktioner returnerer et Response-objekt for at kontrollere resultatet af anmodningen. Du kan bruge følgende responses:

Matchers

Matchers giver dig mulighed for at specificere, hvilke ruter din middleware skal anvendes på. Du kan definere matchers ved hjælp af regulære udtryk eller sti-mønstre. Dette sikrer, at din middleware kun kører, når det er nødvendigt, hvilket forbedrer ydeevnen og reducerer overhead.

Edge Runtime

Next.js middleware kører på Edge Runtime, som er et letvægts JavaScript-runtime-miljø, der kan implementeres tæt på dine brugere. Denne nærhed minimerer latenstid og forbedrer den samlede ydeevne af din applikation, især for globalt distribuerede brugere. Edge Runtime er tilgængelig på Vercels Edge Network og andre kompatible platforme. Edge Runtime har nogle begrænsninger, specifikt brugen af Node.js API'er.

Praktiske Eksempler: Implementering af Middleware-funktioner

1. Godkendelse

Godkendelses-middleware kan bruges til at beskytte ruter, der kræver, at brugere er logget ind. Her er et eksempel på, hvordan man implementerer godkendelse ved hjælp af cookies:


// 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: ['/dashboard/:path*'],
}

Denne middleware tjekker for tilstedeværelsen af en auth_token-cookie. Hvis cookien ikke findes, omdirigeres brugeren til /login-siden. config.matcher specificerer, at denne middleware kun skal køre for ruter under /dashboard.

Globalt Perspektiv: Tilpas godkendelseslogikken til at understøtte forskellige godkendelsesmetoder (f.eks. OAuth, JWT) og integrer med forskellige identitetsudbydere (f.eks. Google, Facebook, Azure AD) for at imødekomme brugere fra forskellige regioner.

2. Autorisation

Autorisations-middleware kan bruges til at kontrollere adgang til ressourcer baseret på brugerroller eller tilladelser. For eksempel kan du have et admin-dashboard, som kun specifikke brugere kan få adgang til.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Eksempel: Hent brugerroller fra et API (erstat med din faktiske logik)
 const userResponse = await fetch('https://api.example.com/userinfo', {
 headers: {
 Authorization: `Bearer ${token}`,
 },
 });
 const userData = await userResponse.json();

 if (userData.role !== 'admin') {
 return NextResponse.redirect(new URL('/unauthorized', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/admin/:path*'],
}

Denne middleware henter brugerens rolle og tjekker, om de har admin-rollen. Hvis ikke, bliver de omdirigeret til en /unauthorized-side. Dette eksempel bruger et placeholder API-endepunkt. Erstat `https://api.example.com/userinfo` med dit faktiske godkendelsesserver-endepunkt.

Globalt Perspektiv: Vær opmærksom på databeskyttelsesforordninger (f.eks. GDPR, CCPA), når du håndterer brugerdata. Implementer passende sikkerhedsforanstaltninger for at beskytte følsomme oplysninger og sikre overholdelse af lokale love.

3. Omdirigering

Omdirigerings-middleware kan bruges til at omdirigere brugere baseret på deres placering, sprog eller andre kriterier. For eksempel kan du omdirigere brugere til en lokaliseret version af din hjemmeside baseret på deres IP-adresse.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const country = request.geo?.country || 'US'; // Standard til USA, hvis geolokalisering fejler

 if (country === 'DE') {
 return NextResponse.redirect(new URL('/de', request.url))
 }

 if (country === 'FR') {
 return NextResponse.redirect(new URL('/fr', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/'],
}

Denne middleware tjekker brugerens land baseret på deres IP-adresse og omdirigerer dem til den relevante lokaliserede version af hjemmesiden (/de for Tyskland, /fr for Frankrig). Hvis geolokaliseringen mislykkes, bruger den som standard den amerikanske version. Bemærk, at dette afhænger af, om geo-egenskaben er tilgængelig (f.eks. når den er implementeret på Vercel).

Globalt Perspektiv: Sørg for, at din hjemmeside understøtter flere sprog og valutaer. Giv brugerne mulighed for manuelt at vælge deres foretrukne sprog eller region. Brug passende dato- og tidsformater for hver lokalitet.

4. A/B-testning

Middleware kan bruges til at implementere A/B-testning ved tilfældigt at tildele brugere til forskellige varianter af en side og spore deres adfærd. Her er et forenklet eksempel:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

function getRandomVariant() {
 return Math.random() < 0.5 ? 'A' : 'B';
}

export function middleware(request: NextRequest) {
 let variant = request.cookies.get('variant')?.value;

 if (!variant) {
 variant = getRandomVariant();
 const response = NextResponse.next();
 response.cookies.set('variant', variant);
 return response;
 }

 if (variant === 'B') {
 return NextResponse.rewrite(new URL('/variant-b', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/'],
}

Denne middleware tildeler brugere til enten variant 'A' eller 'B'. Hvis en bruger ikke allerede har en variant-cookie, tildeles og sættes en tilfældigt. Brugere, der er tildelt variant 'B', omskrives til /variant-b-siden. Du vil derefter spore ydeevnen for hver variant for at afgøre, hvilken der er mest effektiv.

Globalt Perspektiv: Overvej kulturelle forskelle, når du designer A/B-tests. Hvad der fungerer godt i én region, appellerer måske ikke til brugere i en anden. Sørg for, at din A/B-testplatform er i overensstemmelse med privatlivslovgivningen i forskellige regioner.

5. Feature Flags

Feature flags giver dig mulighed for at aktivere eller deaktivere funktioner i din applikation uden at implementere ny kode. Middleware kan bruges til at afgøre, om en bruger skal have adgang til en bestemt funktion baseret på deres bruger-ID, placering eller andre kriterier.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 // Eksempel: Hent feature flags fra et API
 const featureFlagsResponse = await fetch('https://api.example.com/featureflags', {
 headers: {
 'X-User-Id': 'user123',
 },
 });
 const featureFlags = await featureFlagsResponse.json();

 if (featureFlags.new_feature_enabled) {
 // Aktivér den nye funktion
 return NextResponse.next();
 } else {
 // Deaktiver den nye funktion (f.eks. omdiriger til en alternativ side)
 return NextResponse.redirect(new URL('/alternative-page', request.url));
 }
}

export const config = {
 matcher: ['/new-feature'],
}

Denne middleware henter feature flags fra et API og tjekker, om new_feature_enabled-flaget er sat. Hvis det er, kan brugeren få adgang til /new-feature-siden. Ellers bliver de omdirigeret til en /alternative-page.

Globalt Perspektiv: Brug feature flags til gradvist at udrulle nye funktioner til brugere i forskellige regioner. Dette giver dig mulighed for at overvåge ydeevnen og løse eventuelle problemer, før funktionen frigives til et bredere publikum. Sørg også for, at dit feature flagging-system skalerer globalt og giver konsistente resultater uanset brugerens placering. Overvej regionale regulatoriske begrænsninger for funktionsudrulninger.

Avancerede Teknikker

Sammenkædning af Middleware

Du kan kæde flere middleware-funktioner sammen for at udføre en række operationer på en anmodning. Dette kan være nyttigt til at opdele kompleks logik i mindre, mere håndterbare moduler.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const response = NextResponse.next();

 // Første middleware-funktion
 const token = request.cookies.get('auth_token');
 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Anden middleware-funktion
 response.headers.set('x-middleware-custom', 'value');

 return response;
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

Dette eksempel viser to middlewares i én. Den første udfører godkendelse, og den anden sætter en brugerdefineret header.

Brug af Miljøvariabler

Gem følsomme oplysninger, såsom API-nøgler og database-legitimationsoplysninger, i miljøvariabler i stedet for at hardcode dem i dine middleware-funktioner. Dette forbedrer sikkerheden og gør det lettere at administrere din applikations konfiguration.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const API_KEY = process.env.API_KEY;

export async function middleware(request: NextRequest) {
 const response = await fetch('https://api.example.com/data', {
 headers: {
 'X-API-Key': API_KEY,
 },
 });

 // ...
}

export const config = {
 matcher: ['/data'],
}

I dette eksempel hentes API_KEY fra en miljøvariabel.

Fejlhåndtering

Implementer robust fejlhåndtering i dine middleware-funktioner for at forhindre uventede fejl i at få din applikation til at gå ned. Brug try...catch-blokke til at fange undtagelser og logge fejl korrekt.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 try {
 const response = await fetch('https://api.example.com/data');
 // ...
 } catch (error) {
 console.error('Error fetching data:', error);
 return NextResponse.error(); // Eller omdiriger til en fejlside
 }
}

export const config = {
 matcher: ['/data'],
}

Bedste Praksis

Fejlfinding af Almindelige Problemer

Konklusion

Next.js middleware er et kraftfuldt værktøj til at bygge dynamiske og personliggjorte webapplikationer. Ved at mestre anmodningsopsnapning kan du implementere en bred vifte af funktioner, fra godkendelse og autorisation til omdirigering og A/B-testning. Ved at følge de bedste praksisser, der er beskrevet i denne guide, kan du udnytte Next.js middleware til at skabe højtydende, sikre og skalerbare applikationer, der opfylder behovene hos din globale brugerbase. Omfavn kraften i middleware for at låse op for nye muligheder i dine Next.js-projekter og levere exceptionelle brugeroplevelser.