Norsk

Utforsk Next.js middleware, en kraftig funksjon for å avskjære og modifisere innkommende forespørsler. Lær hvordan du implementerer autentisering, autorisasjon, omdirigering og A/B-testing med praktiske eksempler.

Next.js Middleware: Mestre Avskjæring av Forespørsler for Dynamiske Applikasjoner

Next.js middleware gir en fleksibel og kraftig måte å avskjære og modifisere innkommende forespørsler før de når dine ruter. Denne funksjonaliteten lar deg implementere et bredt spekter av funksjoner, fra autentisering og autorisasjon til omdirigering og A/B-testing, alt mens du optimaliserer ytelsen. Denne omfattende guiden vil lede deg gjennom kjernekonseptene i Next.js middleware og demonstrere hvordan du kan utnytte det effektivt.

Hva er Next.js Middleware?

Middleware i Next.js er en funksjon som kjører før en forespørsel fullføres. Den lar deg:

Middleware-funksjoner defineres i middleware.ts (eller middleware.js) filen i roten av prosjektet ditt. De utføres for hver rute i applikasjonen din, eller for spesifikke ruter basert på konfigurerbare matchers.

Nøkkelkonsepter og Fordeler

Request-objektet

request-objektet gir tilgang til informasjon om den innkommende forespørselen, inkludert:

Response-objektet

Middleware-funksjoner returnerer et Response-objekt for å kontrollere utfallet av forespørselen. Du kan bruke følgende responser:

Matchers

Matchers lar deg spesifisere hvilke ruter din middleware skal gjelde for. Du kan definere matchers ved hjelp av regulære uttrykk eller stier. Dette sikrer at din middleware bare kjører når det er nødvendig, noe som forbedrer ytelsen og reduserer overhead.

Edge Runtime

Next.js middleware kjører på Edge Runtime, som er et lettvekts JavaScript-kjøremiljø som kan distribueres nær brukerne dine. Denne nærheten minimerer latens og forbedrer den generelle ytelsen til applikasjonen din, spesielt for globalt distribuerte brukere. Edge Runtime er tilgjengelig på Vercels Edge Network og andre kompatible plattformer. Edge Runtime har noen begrensninger, spesielt bruken av Node.js API-er.

Praktiske Eksempler: Implementering av Middleware-funksjoner

1. Autentisering

Autentiserings-middleware kan brukes til å beskytte ruter som krever at brukere er logget inn. Her er et eksempel på hvordan man implementerer autentisering ved hjelp av 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-funksjonen sjekker for tilstedeværelsen av en auth_token cookie. Hvis cookien ikke finnes, blir brukeren omdirigert til /login-siden. config.matcher spesifiserer at denne middleware-en bare skal kjøre for ruter under /dashboard.

Globalt Perspektiv: Tilpass autentiseringslogikken for å støtte ulike autentiseringsmetoder (f.eks. OAuth, JWT) og integrer med forskjellige identitetsleverandører (f.eks. Google, Facebook, Azure AD) for å imøtekomme brukere fra ulike regioner.

2. Autorisering

Autorisasjons-middleware kan brukes til å kontrollere tilgang til ressurser basert på brukerroller eller tillatelser. For eksempel kan du ha et admin-dashboard som bare spesifikke brukere kan få tilgang 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 brukerroller fra et API (erstatt med din faktiske logikk)
 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-en henter brukerens rolle og sjekker om de har admin-rollen. Hvis ikke, blir de omdirigert til en /unauthorized-side. Dette eksemplet bruker et plassholder-API-endepunkt. Erstatt `https://api.example.com/userinfo` med ditt faktiske autentiseringsserver-endepunkt.

Globalt Perspektiv: Vær oppmerksom på personvernforordninger (f.eks. GDPR, CCPA) når du håndterer brukerdata. Implementer passende sikkerhetstiltak for å beskytte sensitiv informasjon og sikre samsvar med lokale lover.

3. Omdirigering

Omdirigerings-middleware kan brukes til å omdirigere brukere basert på deres plassering, språk eller andre kriterier. For eksempel kan du omdirigere brukere til en lokalisert versjon av nettstedet ditt basert 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 feiler

 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-en sjekker brukerens land basert på IP-adressen deres og omdirigerer dem til den passende lokaliserte versjonen av nettstedet (/de for Tyskland, /fr for Frankrike). Hvis geolokaliseringen feiler, går den som standard til den amerikanske versjonen. Merk at dette er avhengig av at geo-egenskapen er tilgjengelig (f.eks. når den er deployert på Vercel).

Globalt Perspektiv: Sørg for at nettstedet ditt støtter flere språk og valutaer. Gi brukerne muligheten til å manuelt velge sitt foretrukne språk eller region. Bruk passende dato- og tidsformater for hver lokalitet.

4. A/B-testing

Middleware kan brukes til å implementere A/B-testing ved å tilfeldig tildele brukere til forskjellige varianter av en side og spore deres atferd. 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-en tildeler brukere til enten variant 'A' eller 'B'. Hvis en bruker ikke allerede har en variant-cookie, blir en tilfeldig tildelt og satt. Brukere som er tildelt variant 'B' blir omskrevet til /variant-b-siden. Du vil deretter spore ytelsen til hver variant for å avgjøre hvilken som er mest effektiv.

Globalt Perspektiv: Vurder kulturelle forskjeller når du designer A/B-tester. Det som fungerer bra i en region, appellerer kanskje ikke til brukere i en annen. Sørg for at A/B-testingsplattformen din er i samsvar med personvernforordninger i forskjellige regioner.

5. Funksjonsflagg

Funksjonsflagg lar deg aktivere eller deaktivere funksjoner i applikasjonen din uten å deployere ny kode. Middleware kan brukes til å avgjøre om en bruker skal ha tilgang til en spesifikk funksjon basert på bruker-ID, plassering eller andre kriterier.


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

export async function middleware(request: NextRequest) {
 // Eksempel: Hent funksjonsflagg 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) {
 // Aktiver den nye funksjonen
 return NextResponse.next();
 } else {
 // Deaktiver den nye funksjonen (f.eks. omdiriger til en alternativ side)
 return NextResponse.redirect(new URL('/alternative-page', request.url));
 }
}

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

Denne middleware-en henter funksjonsflagg fra et API og sjekker om new_feature_enabled-flagget er satt. Hvis det er det, kan brukeren få tilgang til /new-feature-siden. Ellers blir de omdirigert til en /alternative-page.

Globalt Perspektiv: Bruk funksjonsflagg for å gradvis rulle ut nye funksjoner til brukere i forskjellige regioner. Dette lar deg overvåke ytelsen og håndtere eventuelle problemer før funksjonen lanseres for et bredere publikum. Sørg også for at funksjonsflaggsystemet ditt skalerer globalt og gir konsistente resultater uavhengig av brukerens plassering. Vurder regionale regulatoriske begrensninger for funksjonsutrullinger.

Avanserte Teknikker

Kjeding av Middleware

Du kan kjede flere middleware-funksjoner sammen for å utføre en serie operasjoner på en forespørsel. Dette kan være nyttig for å bryte ned kompleks logikk i mindre, mer 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-funksjon
 const token = request.cookies.get('auth_token');
 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Andre middleware-funksjon
 response.headers.set('x-middleware-custom', 'value');

 return response;
}

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

Dette eksemplet viser to middlewares i ett. Den første utfører autentisering og den andre setter en tilpasset header.

Bruk av Miljøvariabler

Lagre sensitiv informasjon, som API-nøkler og databasetilganger, i miljøvariabler i stedet for å hardkode dem i dine middleware-funksjoner. Dette forbedrer sikkerheten og gjør det enklere å administrere applikasjonens konfigurasjon.


// 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 eksemplet hentes API_KEY fra en miljøvariabel.

Feilhåndtering

Implementer robust feilhåndtering i dine middleware-funksjoner for å forhindre at uventede feil krasjer applikasjonen din. Bruk try...catch-blokker for å fange unntak og logge feil på en hensiktsmessig måte.


// 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 feilside
 }
}

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

Beste Praksis

Feilsøking av Vanlige Problemer

Konklusjon

Next.js middleware er et kraftig verktøy for å bygge dynamiske og personlig tilpassede webapplikasjoner. Ved å mestre avskjæring av forespørsler kan du implementere et bredt spekter av funksjoner, fra autentisering og autorisasjon til omdirigering og A/B-testing. Ved å følge beste praksis som er beskrevet i denne guiden, kan du utnytte Next.js middleware til å skape høytytende, sikre og skalerbare applikasjoner som imøtekommer behovene til din globale brukerbase. Omfavn kraften i middleware for å låse opp nye muligheter i dine Next.js-prosjekter og levere eksepsjonelle brukeropplevelser.

Next.js Middleware: Mestre Avskjæring av Forespørsler for Dynamiske Applikasjoner | MLOG