Middleware i Next.js: autentisering, omdirigeringar och mer
Middleware körs på edge-nätverket innan varje request. Lär dig använda det för autentisering, omdirigeringar och A/B-testning.
Vad är Middleware?
Middleware i Next.js är kod som körs innan en request når din sida, layout eller Route Handler. Det sker på edge-nätverket, nära användaren geografiskt, vilket gör det snabbt men också begränsat till en delmängd av webbplattformen.
Filen heter middleware.js och placeras i projektroten, på samma nivå som app/-mappen:
projekt/
app/
middleware.js ← körs för varje matchande request
next.config.js
Middleware passar för åtgärder som måste ske tidigt i request-kedjan: kontrollera autentisering, vidarebefordra begäran till en annan URL, sätta cookies, eller läsa och skriva headers. Det är inte rätt plats för tung serverlogik eller databasfrågor.
Din första middleware
Den enklaste möjliga middleware vidarebefordrar bara requesten vidare utan att göra något:
import { NextResponse } from "next/server";
export function middleware(request) {
return NextResponse.next();
}
NextRequest utökar den vanliga Request-klassen med Next.js-specifika egenskaper som nextUrl och cookies. NextResponse ger dig verktyg för att skapa omdirigeringar, rewrites och modifiera headers.
Nedan är en minimal middleware som redirectar /gammal-sida till /ny-sida:
import { NextResponse } from "next/server";
export function middleware(request) {
if (request.nextUrl.pathname === "/gammal-sida") {
return NextResponse.redirect(new URL("/ny-sida", request.url));
}
return NextResponse.next();
}
Autentisering med Middleware
Ett vanligt användningsfall är att skydda routes som kräver inloggning. Middleware kan läsa cookies och headers, validera en token och omdirigera oinloggade användare till inloggningssidan.
import { NextResponse } from "next/server";
export function middleware(request) {
const token = request.cookies.get("session-token")?.value;
const { pathname } = request.nextUrl;
const skyddadeRoutes = ["/dashboard", "/konto", "/admin"];
const begarSkyddadRoute = skyddadeRoutes.some((route) =>
pathname.startsWith(route),
);
if (begarSkyddadRoute && !token) {
const inloggningsUrl = new URL("/logga-in", request.url);
inloggningsUrl.searchParams.set("atervänd", pathname);
return NextResponse.redirect(inloggningsUrl);
}
return NextResponse.next();
}
Det är viktigt att förstå att middleware på edge-nätverket inte kan göra fullständig JWT-validering med Node.js-bibliotek som jsonwebtoken. Du kan verifiera signaturer med Web Crypto API eller använda ett bibliotek som är byggt för edge-miljön, exempelvis jose.
import { jwtVerify } from "jose";
export async function middleware(request) {
const token = request.cookies.get("session-token")?.value;
if (!token) {
return NextResponse.redirect(new URL("/logga-in", request.url));
}
try {
const hemlig = new TextEncoder().encode(process.env.JWT_HEMLIGHET);
await jwtVerify(token, hemlig);
return NextResponse.next();
} catch {
return NextResponse.redirect(new URL("/logga-in", request.url));
}
}
Omdirigeringar och rewrites
NextResponse.redirect() skickar ett 307-svar till webbläsaren. För permanenta omdirigeringar, använd statuskod 308:
return NextResponse.redirect(new URL("/ny-sida", request.url), 308);
Rewrites skiljer sig från redirects: URL:en i webbläsaren förblir oförändrad, men Next.js serverar en annan sida internt. Det är användbart för A/B-testning eller för att dölja interna URL-strukturer.
import { NextResponse } from "next/server";
export function middleware(request) {
const variation = Math.random() < 0.5 ? "a" : "b";
if (request.nextUrl.pathname === "/landningssida") {
return NextResponse.rewrite(
new URL(`/landningssida-${variation}`, request.url),
);
}
return NextResponse.next();
}
För konsekvent A/B-testning sätter du variationen i en cookie vid första besöket och läser den vid efterföljande requests.
Matcher och sökvägar
Som standard körs middleware för varje request, inklusive statiska tillgångar och Next.js-interna filer. Det är onödigt och kan påverka prestandan. Begränsa middleware till relevanta sökvägar med config.matcher:
export const config = {
matcher: [
"/dashboard/:path*",
"/konto/:path*",
"/admin/:path*",
"/api/:path*",
],
};
Du kan också använda ett negativt lookahead-mönster för att exkludera statiska filer och Next.js-internals:
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|webp)).*)",
],
};
Matchning sker med path-to-regexp-syntax och utvärderas vid byggtid, inte runtime. Dynamiska värden från miljövariabler fungerar inte i matcher.
Begränsningar
Edge Runtime saknar tillgång till Node.js-standardbiblioteket. Det innebär att du inte kan använda moduler som fs, path, crypto (Node.js-versionen) eller de flesta npm-paket som förutsätter en Node.js-miljö.
Vad du kan göra i middleware:
- Läsa och skriva cookies och headers
- Omdirigera och rewrite requests
- Returnera ett Response-objekt direkt
- Anropa externa API:er med
fetch() - Använda Web Crypto API
Vad du inte kan göra:
- Fråga en databas direkt (för långsamt och saknar Node.js-drivrutiner)
- Använda Node.js-specifika moduler
- Komma åt filsystemet
Om din logik kräver databasåtkomst, flytta den till en Route Handler och anropa den från middleware vid behov, eller hantera det i Server Components efter att middleware vidarebefordrat requesten.
Sammanfattning
Middleware ger dig ett tidigt intercepteringslager för request-hantering: autentiseringskontroller, omdirigeringar och rewrites utan att sidans rendering behöver starta. Begränsa det till matcher för att hålla prestandan god, och undvik komplex logik som förutsätter Node.js-miljön. Håll middleware snabb och enkel, och delegera tung logik till Route Handlers eller Server Components.
