Next.js 16 Middleware in 2026: Edge Runtime, Authenticatie en Sollicitatievragen

Uitgebreide handleiding over Next.js 16 Middleware met Edge Runtime, authenticatiepatronen, URL rewriting en veelgestelde technische sollicitatievragen voor frontend-ontwikkelaars.

Next.js 16 Middleware Edge Runtime en Authenticatie

Next.js 16 Middleware draait voordat elke request de server bereikt, waardoor het de eerste verdedigingslinie vormt voor authenticatie, lokalisatie en request-manipulatie. Het begrijpen van middleware is essentieel voor het bouwen van productie-applicaties en een veelvoorkomend onderwerp in frontend-sollicitatiegesprekken.

Middleware draait op de Edge

Next.js 16 Middleware draait standaard in de Edge Runtime, wat betekent dat het in datacenters dicht bij gebruikers draait met cold starts van minder dan een milliseconde. Dit maakt het ideaal voor authenticatiecontroles en redirects die moeten plaatsvinden voordat de pagina wordt gerenderd.

Hoe Next.js 16 Middleware Onder de Motorkap Werkt

Middleware in Next.js 16 onderschept requests voordat ze de route handler of page component bereiken. Het middleware-bestand moet in de root van het project worden geplaatst (naast app/ of pages/) en exporteert een standaardfunctie die een NextRequest-object ontvangt.

De Edge Runtime-beperking betekent dat middleware geen Node.js API's zoals fs of Buffer kan gebruiken. Het draait op V8 isolates, vergelijkbaar met Cloudflare Workers, wat globale distributie mogelijk maakt maar de beschikbare API's beperkt tot webstandaarden.

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

export function middleware(request: NextRequest) {
  // Access request headers, cookies, and URL
  const token = request.cookies.get('session')?.value
  const pathname = request.nextUrl.pathname

  // Log for debugging (visible in Vercel logs)
  console.log(`Middleware: ${request.method} ${pathname}`)

  // Continue to the route handler
  return NextResponse.next()
}

// Configure which paths trigger middleware
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

De matcher-configuratie gebruikt een regex-achtige syntax om te definiëren welke paden de middleware activeren. Zonder deze configuratie draait middleware op elke request, inclusief statische assets.

Authenticatiepatronen met Next.js Middleware

Middleware blinkt uit in authenticatie omdat het draait voordat enige paginacode wordt uitgevoerd. Een gebruiker zonder geldige sessie ziet nooit beschermde content, zelfs niet kort. Dit verschilt van client-side authenticatiecontroles die beschermde content kort kunnen laten zien voordat ze doorverwijzen.

Het volgende patroon valideert een sessietoken en leidt niet-geauthenticeerde gebruikers om. Het integreert met elke auth-provider die sessiegegevens opslaat in cookies of headers.

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

const protectedPaths = ['/dashboard', '/settings', '/profile']
const authPaths = ['/login', '/signup']

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl
  const sessionToken = request.cookies.get('session')?.value

  // Check if path requires authentication
  const isProtectedPath = protectedPaths.some(path => 
    pathname.startsWith(path)
  )
  const isAuthPath = authPaths.some(path => 
    pathname.startsWith(path)
  )

  // Validate session token (call auth service)
  const isValidSession = sessionToken 
    ? await validateSession(sessionToken)
    : false

  // Redirect unauthenticated users to login
  if (isProtectedPath && !isValidSession) {
    const loginUrl = new URL('/login', request.url)
    loginUrl.searchParams.set('callbackUrl', pathname)
    return NextResponse.redirect(loginUrl)
  }

  // Redirect authenticated users away from auth pages
  if (isAuthPath && isValidSession) {
    return NextResponse.redirect(new URL('/dashboard', request.url))
  }

  return NextResponse.next()
}

async function validateSession(token: string): Promise<boolean> {
  // Call auth API endpoint or decode JWT
  // Edge-compatible: use fetch, not Node.js crypto
  try {
    const response = await fetch('https://api.example.com/validate', {
      headers: { Authorization: `Bearer ${token}` },
    })
    return response.ok
  } catch {
    return false
  }
}

De callbackUrl-parameter bewaart de oorspronkelijke bestemming, zodat gebruikers na het inloggen op de pagina landen die ze oorspronkelijk hadden opgevraagd.

Path Matching en de Matcher Configuratie

De matcher-configuratie bepaalt welke requests de middleware activeren. Fouten hier leiden tot prestatieproblemen (middleware die draait op elke statische asset) of beveiligingslekken (beschermde paden die geen auth-controles activeren).

Next.js 16 ondersteunt drie matcher-syntaxen: string-paden, padpatronen met parameters en regex-achtige patronen met negatieve lookaheads.

middleware.tstypescript
// Option 1: Simple string paths
export const config = {
  matcher: ['/dashboard/:path*', '/api/:path*'],
}

// Option 2: Exclude static assets with negative lookahead
export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'],
}

// Option 3: Conditional matching with has/missing
export const config = {
  matcher: [
    {
      source: '/api/:path*',
      has: [{ type: 'header', key: 'Authorization' }],
    },
    {
      source: '/dashboard/:path*',
      missing: [{ type: 'cookie', key: 'session' }],
    },
  ],
}

De has- en missing-condities in optie 3 voegen logica toe voordat de middleware zelfs wordt uitgevoerd. Dit is efficiënter dan controleren binnen de middleware-functie.

Klaar om je React / Next.js gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Request- en Response-Manipulatie in Middleware

Naast authenticatie kan middleware requests modificeren voordat ze route handlers bereiken en responses voordat ze de client bereiken. Veelvoorkomende use cases zijn het toevoegen van security headers, URL rewriting voor A/B-tests en het injecteren van geolocatiegegevens.

De NextResponse-klasse biedt methodes voor elk type modificatie. Rewrites veranderen de bestemming zonder de browser-URL te wijzigen, terwijl redirects beide bijwerken.

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

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

  // Add security headers to all responses
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-Content-Type-Options', 'nosniff')
  response.headers.set(
    'Referrer-Policy', 
    'strict-origin-when-cross-origin'
  )

  // Inject geolocation into request headers for route handlers
  const geo = request.geo
  if (geo?.country) {
    response.headers.set('x-user-country', geo.country)
    response.headers.set('x-user-city', geo.city ?? 'unknown')
  }

  return response
}

Geolocatiegegevens (request.geo) worden ingevuld door Vercel's Edge Network. Self-hosted deployments moeten dit configureren via de hosting-provider of een externe IP-geolocatiedienst gebruiken.

URL Rewriting voor A/B Tests en Feature Flags

Middleware rewrites maken het mogelijk om verschillende pagina's te serveren op basis van cookies, headers of willekeurige toewijzing zonder dat de client het weet. Dit patroon drijft A/B-testframeworks en geleidelijke feature-rollouts aan.

De rewrite vindt plaats op de edge, dus beide varianten hebben dezelfde URL en profiteren waar gepast van edge caching.

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

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl

  // Check for existing variant assignment
  let variant = request.cookies.get('ab-variant')?.value

  // Assign variant if not set (50/50 split)
  if (!variant && pathname === '/pricing') {
    variant = Math.random() < 0.5 ? 'control' : 'treatment'
    const response = NextResponse.rewrite(
      new URL(`/pricing/${variant}`, request.url)
    )
    response.cookies.set('ab-variant', variant, {
      maxAge: 60 * 60 * 24 * 30, // 30 days
      httpOnly: true,
    })
    return response
  }

  // Rewrite to assigned variant
  if (variant && pathname === '/pricing') {
    return NextResponse.rewrite(
      new URL(`/pricing/${variant}`, request.url)
    )
  }

  return NextResponse.next()
}

De cookie bewaart de varianttoewijzing, zodat gebruikers bij terugkerende bezoeken dezelfde versie zien. De 30-daagse vervaldatum balanceert experimentconsistentie met de mogelijkheid om gebruikers aan nieuwe experimenten toe te wijzen.

Edge Runtime Beperkingen en Workarounds

De Edge Runtime ruilt Node.js-compatibiliteit in voor globale distributie en snelle cold starts. Middleware kan geen Node.js-specifieke modules importeren, wat invloed heeft op bibliotheken zoals bcrypt, jsonwebtoken (bij gebruik van RS256) en databaseclients die afhankelijk zijn van TCP-sockets.

De Next.js Edge Runtime-documentatie somt ondersteunde API's op. Web Crypto, fetch en de meeste Web Platform API's werken. Zware berekeningen moeten worden verplaatst naar API-routes die in Node.js draaien.

middleware.ts - JWT validation without jsonwebtokentypescript
import { jwtVerify } from 'jose' // Edge-compatible JWT library
import type { NextRequest } from 'next/server'

const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)

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

  if (!token) {
    return redirectToLogin(request)
  }

  try {
    // jose library works in Edge Runtime
    const { payload } = await jwtVerify(token, JWT_SECRET)
    
    // Token is valid, check expiration
    if (payload.exp && payload.exp < Date.now() / 1000) {
      return redirectToLogin(request)
    }

    return NextResponse.next()
  } catch {
    // Invalid token signature or format
    return redirectToLogin(request)
  }
}

function redirectToLogin(request: NextRequest) {
  const url = new URL('/login', request.url)
  url.searchParams.set('callbackUrl', request.nextUrl.pathname)
  return NextResponse.redirect(url)
}

De jose-bibliotheek biedt Edge-compatibele JWT-operaties. Het gebruikt Web Crypto onder de motorkap en vermijdt de Node.js crypto-module.

Veelgestelde Next.js Middleware Sollicitatievragen

Interviewers vragen naar middleware om begrip van de request-lifecycle, beveiligingspatronen en Edge computing-beperkingen te beoordelen. Deze vragen komen voor in senior frontend- en fullstack-rollen die werken met Next.js.

Waar draait middleware in de request-lifecycle?

Middleware draait nadat de request de Next.js-server bereikt maar voordat er route matching of page rendering plaatsvindt. Op Vercel draait het op de Edge, wat het dichtstbijzijnde datacenter bij de gebruiker betekent. Deze plaatsing maakt het ideaal voor authenticatie en redirects omdat ongeldige requests nooit de origin-server bereiken.

Wat kan middleware niet doen vergeleken met API-routes?

Middleware draait in de Edge Runtime, niet Node.js. Het kan geen ingebouwde Node.js-modules gebruiken (fs, path, crypto met bepaalde algoritmes), TCP-gebaseerde databaseclients of npm-packages die afhankelijk zijn van Node.js API's. Zware berekeningen moeten plaatsvinden in API-routes of Server Components.

Hoe wordt authenticatie in middleware afgehandeld zonder te blokkeren?

Het patroon omvat het controleren op een sessiecookie, het valideren tegen een auth-endpoint of door een JWT-handtekening te verifiëren, en doorverwijzen als ongeldig. Om te voorkomen dat elke request wordt geblokkeerd, gebruikt men de matcher-configuratie om middleware alleen op beschermde paden uit te voeren. Stateless JWT-validatie is sneller dan het aanroepen van een externe auth-service bij elke request.

Wat gebeurt er als middleware een fout gooit?

Een onafgehandelde fout in middleware retourneert een 500-response naar de client. De pagina wordt nooit gerenderd. Het wrappen van middleware-logica in try-catch en het retourneren van een fallback-response (vaak NextResponse.next()) voorkomt complete request-failures. Het loggen van de fout voordat wordt doorgegaan helpt bij debugging.

Voor diepgaandere oefening met deze concepten behandelt de Next.js Middleware en Auth sollicitatievragen-module aanvullende scenario's.

Debugging van Middleware in Ontwikkeling en Productie

Middleware-bugs zijn lastig omdat de code op de edge draait, niet in de browser DevTools. Development mode toont middleware-logs in de terminal, maar productie vereist goede logging-infrastructuur.

De volgende aanpak logt middleware-uitvoering met voldoende context om problemen te debuggen zonder gevoelige gegevens bloot te stellen.

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

export function middleware(request: NextRequest) {
  const start = Date.now()
  const requestId = crypto.randomUUID()

  // Log request start
  console.log(JSON.stringify({
    type: 'middleware_request',
    requestId,
    method: request.method,
    path: request.nextUrl.pathname,
    userAgent: request.headers.get('user-agent')?.slice(0, 100),
    country: request.geo?.country,
  }))

  // Process request
  const response = processRequest(request)

  // Log completion
  console.log(JSON.stringify({
    type: 'middleware_response',
    requestId,
    duration: Date.now() - start,
    status: response.status,
  }))

  // Pass request ID to route handlers
  response.headers.set('x-request-id', requestId)
  return response
}

function processRequest(request: NextRequest): NextResponse {
  // Middleware logic here
  return NextResponse.next()
}

Op Vercel verschijnen deze logs in het Functions-tabblad. Self-hosted deployments moeten logs naar een service zoals Datadog sturen of gestructureerde logging gebruiken die het hostingplatform kan verwerken.

Middleware Performance Best Practices

Middleware draait op elke gematchte request. Een trage middleware-functie voegt latentie toe aan elke paginalading. Het doel is om middleware-uitvoering voor de meeste requests in minder dan 5ms te voltooien.

  • Minimaliseer async-operaties: Elke await voegt latentie toe. Cache validatieresultaten waar mogelijk.
  • Gebruik matcher-config: Sluit statische assets en publieke paden uit die geen middleware-logica nodig hebben.
  • Vermijd externe calls bij elke request: Valideer JWT's lokaal in plaats van een auth-service aan te roepen. Cache resultaten in cookies waar gepast.
  • Houd de bundle klein: Middleware heeft zijn eigen bundle size-limiet (1MB op Vercel). Importeer alleen wat nodig is.

De React Next.js-technologiepagina op /technologies/react-next behandelt gerelateerde concepten zoals Server Components en data-fetching patronen die middleware-kennis aanvullen.

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Next.js 16 Middleware Checklist voor Productie

  • Plaats middleware in de project-root als middleware.ts, niet binnen app/ of pages/
  • Configureer de matcher om _next/static, _next/image en publieke assets uit te sluiten van middleware-uitvoering
  • Gebruik Edge-compatibele bibliotheken voor JWT-validatie, zoals jose in plaats van jsonwebtoken
  • Sla callback-URL's op in query-parameters bij doorverwijzing naar login, zodat gebruikers terugkeren naar hun beoogde bestemming
  • Voeg security headers toe in middleware voor consistente toepassing over alle routes
  • Log middleware-uitvoering met request ID's om requests door het systeem te traceren
  • Houd externe API-calls tot een minimum door tokens lokaal te valideren en gebruikersgegevens te cachen in gesigneerde cookies
Dagelijkse challenge

Zie jij de bug in React / Next.js?

Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Anthony Fillion-Maillet

Geschreven door

Anthony Fillion-Maillet

Oprichter van SharpSkill

Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.

Bijgewerkt op 20 september 2026

Tags

#nextjs
#middleware
#edge-runtime
#authenticatie
#sollicitatievragen

Delen

Gerelateerde artikelen