Ik heb Next.js-applicaties ondersteund sinds versie 9. Sommige daarvan draaien nog steeds in productie en serveren miljoenen verzoeken. Anderen? Die zijn upgrade-nachtmerries geworden omdat iemand (oké, soms ik) onderhoud zes maanden lang heeft overgeslagen en plotseling 47 grote versie-updates, drie verouderde API's en een CVE tegenkwam die het beveiligingsteam niet lekker sliep.

Next.js beweegt snel. Het framework bracht tot 2024 en 2025 ruwweg elke zes maanden grote releases uit, en 2026 zet dat tempo voort. Als je je Next.js-project niet actief onderhoudt, verzamel je technische schuld die sneller oploopt dan je zou verwachten. Deze gids behandelt alles wat ik heb geleerd over het gezond houden van Next.js-applicaties, van wekelijkse afhankelijkheidscontroles tot jaarlijkse grote versie-migraties. En als je al weet dat je hulp nodig hebt, dien je RFP in en we kijken ernaar.

Inhoudsopgave

Waarom Next.js-onderhoud meer uitmaakt dan je denkt

Laat me je wat nummers geven. Volgens Snyk's 2025 State of Open Source Security-rapport heeft het gemiddelde JavaScript-project 49 directe afhankelijkheden en meer dan 500 transitieve afhankelijkheden. Elk ervan is een potentieel aanvalsvlak. De mediane tijd tussen het publiceren van een kwetsbaarheid en het verschijnen van een exploit in het wild daalde naar 7 dagen in 2025. Zeven dagen.

Next.js introduceert specifieke onderhoudsoverwegingen die vanilla React-apps niet hebben:

  • Server-side rendering-aanvalsvlak -- je Next.js-app voert code uit op een server, niet alleen in de browser. Een kwetsbare afhankelijkheid aan de serverzijde is veel gevaarlijker dan een die in een browser is ingesloten.
  • API-routes en Server Actions -- dit zijn volledige backend-eindpunten. Ze hebben dezelfde veiligheidsstrengheid nodig als elke Express- of Fastify-API.
  • Build pipeline-afhankelijkheden -- SWC, webpack/Turbopack, PostCSS-processoren en afbeeldingsoptimalisatie hebben allemaal hun eigen afhankelijkheidsbomen.
  • Middleware-uitvoering -- loopt op de rand in veel implementaties, met zijn eigen set compatibiliteits- en veiligheidsoverwegingen.

Naast beveiliging is er de SEO-hoek. Google's Core Web Vitals zijn een rankingfactor, en Next.js prestatieregressies van verouderde code kunnen je zoekzichtbaarheid rechtstreeks treffen. We hebben clients bij Social Animal zien 15-20% verloren organisch verkeer terugwinnen door simpelweg van Next.js 13 naar 15 te upgraden en opgehoopte prestatieproblemen op te lossen.

Een onderhoudsschema bouwen dat echt werkt

Het sleutelinzicht dat ik heb opgedaan na het onderhouden van tientallen Next.js-projecten: onderhoud is makkelijker wanneer het saai en routineus is. Het moment dat het een 'project' wordt, is het moment waarop het al achterstand heeft.

Hier is het schema dat ik gebruik:

Frequentie Taak Tijdsschatting
Wekelijks Review Dependabot/Renovate PRs, merge patch-updates 30-60 min
Elke twee weken Voer npm audit uit en los bevindingen op 30 min
Maandelijks Update minorversies, review changelog op breaking changes 2-4 uur
Driemaandelijks Audit ongebruikte afhankelijkheden, review bundelgrootte, update Node.js 4-8 uur
Per release Grote Next.js-versie migratie 8-40 uur
Jaarlijks Volledige beveiligingsaudit, afhankelijkheden overhaul, infrastructuurbeoordeling 16-40 uur

Het wekelijkse ritme

Elke maandagochtend controleer ik de geautomatiseerde PRs die tools zoals Renovate of Dependabot hebben geopend. Patch-updates (1.2.3 → 1.2.4) worden samengevoegd nadat CI is geslaagd. Dit duurt maximaal 30 minuten en voorkomt de situatie "200 verouderde pakketten".

# Snelle gezondheidscontrole die ik elke week uitvoer
npx npm-check-updates --target patch
npm audit --audit-level=moderate
npx next info

De maandelijkse diepe duik

Eenmaal per maand kijk ik naar minorversion-bumps. Deze kunnen nieuwe functies bevatten, maar zouden geen bestaande API's moeten onderbreken. Nadruk op "zouden". Lees altijd changelogs.

# Controleer op minore updates
npx npm-check-updates --target minor

# Bekijk wat zou veranderen
npx npm-check-updates --target minor --format group

Ik groepeer gerelateerde updates samen. @next/font afzonderlijk van next updaten, is om moeilijkheden vragen. Ze zouden in sync moeten gaan.

Afhankelijkheidsupgrades: het stap-voor-stapproces

Dit is waar de meeste teams het fout doen. Ze voeren npm update uit, bidden, en pushen. Dit is wat ik echt doe:

Stap 1: Begrijp wat je hebt

Voordat je iets upgrade, ken je afhankelijkheidlandschap.

# Geef alle verouderde pakketten weer met details
npm outdated

# Genereer een afhankelijkheidsboom voor een specifiek pakket
npm ls react-dom

# Controleer op duplicaten in je lock-bestand
npx depcheck

Stap 2: Categoriseer updates op risico

Niet alle updates zijn gelijk. Ik sorteer ze in buckets:

Risiconiveau Voorbeelden Benadering
Laag Patch-updates, alleen dev-afhankelijkheden, type definitie-updates Batch en merge
Gemiddeld Minorversion-bumps in runtime-afhankelijkheden, Next.js patch-updates Update individueel, run volledige test-suite
Hoog Majorversion-bumps, Next.js minor/major-updates, React-updates Dedicated branch, grondige tests, gefaseerde uitrol
Kritiek Beveiligingspatches voor runtime-afhankelijkheden Dezelfde dag update, noodprocedure

Stap 3: Maak een geïsoleerde branch

Voor alles voorbij patch-updates:

git checkout -b deps/update-2026-05

# Update specifieke pakketten
npm install next@latest react@latest react-dom@latest

# Voer de build onmiddellijk uit -- wacht niet
npm run build

# Voer je test-suite uit
npm test

# Controleer op type-fouten als je TypeScript gebruikt
npx tsc --noEmit

Stap 4: Verifieer runtime-gedrag

We liepen dit vorig jaar tegen bij een client: de build slaagde, tests waren groen, en alles zag er op papier prima uit. Toen begonnen Server Components plotseling hydration-mismatches te gooien in productie omdat een afhankelijkheid zijn uitvoerformaat had veranderd in een minorbump. Een geslaagde build en tests betekenen niet dat alles werkt.

Ik doen altijd het volgende:

  1. Voer de dev-server uit en klik handmatig door kritieke paden
  2. Controleer dat Server Components nog steeds correct renderen (hydration-mismatches houden ervan om zich te verbergen)
  3. Verifieer dat API-routes verwachte reacties retourneren
  4. Test middleware-gedrag, vooral auth-flows
  5. Controleer of afbeeldingsoptimalisatie nog steeds werkt (de next/image-component is in verschillende updates kapot gegaan)

Als je midden in het bepalen van deze soort werk zit en een team achter je nodig hebt, dien dan je RFP in en we kunnen samen de juiste benadering bepalen.

Stap 5: Monitor na deploy

Voeg niet samen en vergeet. Bewak je error tracking (Sentry, LogRocket) en performance monitoring voor 48 uur na het deployen van afhankelijkheidsupdates.

Beveiligingsharding voor Next.js in 2026

Beveiliging in Next.js is aanzienlijk geëvolueerd. Het Server Actions-model dat in Next.js 14 werd geïntroduceerd en tot 15 en 16 werd volwassen, heeft het aanvalsvlak volledig veranderd. Dit is waar je nu op moet focussen.

Server Action-beveiliging

Server Actions zijn in wezen openbare API-eindpunten. Behandel ze als zodanig.

// SLECHT -- geen validatie, geen auth-controle
'use server'
export async function deleteUser(userId: string) {
  await db.user.delete({ where: { id: userId } })
}

// GOED -- gevalideerd, geverifieerd, geautoriseerd
'use server'
import { z } from 'zod'
import { auth } from '@/lib/auth'

const deleteUserSchema = z.object({
  userId: z.string().uuid(),
})

export async function deleteUser(rawData: unknown) {
  const session = await auth()
  if (!session?.user) throw new Error('Unauthorized')
  
  const { userId } = deleteUserSchema.parse(rawData)
  
  // Controleer of de gebruiker toestemming heeft om deze specifieke gebruiker te verwijderen
  if (session.user.role !== 'admin') throw new Error('Forbidden')
  
  await db.user.delete({ where: { id: userId } })
  revalidatePath('/admin/users')
}

Beveiligingsheaders

Je next.config.js (of next.config.ts in 2026 -- TypeScript-configuratie is stabiel sinds Next.js 15) zou beveiligingsheaders moeten instellen:

// next.config.ts
import type { NextConfig } from 'next'

const securityHeaders = [
  { key: 'X-DNS-Prefetch-Control', value: 'on' },
  { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
  { key: 'X-Frame-Options', value: 'SAMEORIGIN' },
  { key: 'X-Content-Type-Options', value: 'nosniff' },
  { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
  { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
]

const config: NextConfig = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: securityHeaders,
      },
    ]
  },
}

export default config

Content Security Policy

CSP is moeilijker in Next.js vanwege inline scripts voor hydration. De nonce-gebaseerde benadering werkt het best:

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

export function middleware(request: NextRequest) {
  const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
  const cspHeader = `
    default-src 'self';
    script-src 'self' 'nonce-${nonce}' 'strict-dynamic';
    style-src 'self' 'nonce-${nonce}';
    img-src 'self' blob: data:;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
  `
  
  const response = NextResponse.next()
  response.headers.set('Content-Security-Policy', cspHeader.replace(/\s{2,}/g, ' ').trim())
  response.headers.set('x-nonce', nonce)
  return response
}

npm audit-workflow

Voer niet alleen npm audit uit. Verwerk de resultaten systematisch:

# Genereer een JSON-rapport voor tracking
npm audit --json > audit-report.json

# Repareer wat auto-kan worden gerepareerd
npm audit fix

# Voor koppige problemen die major bumps nodig hebben
npm audit fix --force  # zorgvuldig met deze

# Controleer specifieke pakketten op bekende kwetsbaarheden
npx is-my-node-vulnerable

Voor pakketten waar de fix nog niet beschikbaar is, gebruik npm audit-overrides in package.json:

{
  "overrides": {
    "vulnerable-transitive-dep": ">=2.1.1"
  }
}

Geautomatiseerde tools en CI/CD-integratie

Automatisering is wat teams die goed onderhouden van teams die dat niet doen onderscheidt. Dit is mijn stack voor 2026:

Renovate Bot-configuratie

Ik geef de voorkeur aan Renovate boven Dependabot voor Next.js-projecten. Het is meer configureerbaar en handelt monorepo's beter af.

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:recommended"],
  "schedule": ["every weekend"],
  "packageRules": [
    {
      "matchPackageNames": ["next", "react", "react-dom", "@types/react", "@types/react-dom"],
      "groupName": "React + Next.js core",
      "automerge": false
    },
    {
      "matchUpdateTypes": ["patch"],
      "matchPackagePatterns": ["eslint", "prettier", "@types/"],
      "automerge": true,
      "automergeType": "branch"
    },
    {
      "matchPackagePatterns": ["*"],
      "matchUpdateTypes": ["major"],
      "enabled": true,
      "automerge": false,
      "labels": ["major-update", "needs-review"]
    }
  ],
  "vulnerabilityAlerts": {
    "enabled": true,
    "labels": ["security"]
  }
}

CI-pijplijn voor afhankelijkheidsupdates

Je CI zou meer moeten doen dan testen uitvoeren wanneer afhankelijkheden veranderen:

# .github/workflows/dependency-check.yml
name: Dependency Update Validation
on:
  pull_request:
    paths:
      - 'package.json'
      - 'package-lock.json'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'
      - run: npm ci
      - run: npm run build
      - run: npm test
      - run: npm audit --audit-level=high
      - name: Bundle size check
        run: npx size-limit
      - name: Lighthouse CI
        uses: treosh/lighthouse-ci-action@v12
        with:
          configPath: './lighthouserc.json'

Socket.dev voor supply chain-beveiliging

Ik heb Socket.dev aan elk project dat ik onderhoud toegevoegd. Het vangt dingen op die npm audit mist, zoals pakketten die plotseling netwerk-oproepen of bestandssysteemtoegang in nieuwe versies toevoegen. Het heeft twee verdachte updates in projecten waar ik aan heb gewerkt in het afgelopen jaar opgemerkt.

Omgaan met grote Next.js-versiemigraties

Grote versiemigraties verdienen hun eigen sectie omdat ze de meest tijd kost en risicovollste onderhoudstaak zijn.

Het migratieplaybook

  1. Lees de officiële migratiegids volledig voordat je code schrijft. Vercel publiceert gedetailleerde codemods en gidsen voor elke grote release.

  2. Voer eerst de codemods uit. Next.js biedt geautomatiseerde codemods die de meeste hernamingen en API-wijzigingen afhandelen:

npx @next/codemod@latest upgrade
  1. Los compiler-fouten op. Na de codemod, voer TypeScript-compilatie uit en repareer wat stuk is.

  2. Test Server Components- en Client Components-grenzen. Grote versies veranderen vaak standaardgedrag rond componenttypen.

  3. Verifieer data-fetchpatronen. De verschuiving van getServerSideProps naar Server Components was Next.js's grootste breaking change ooit (Next.js 13). Volgende versies hebben dit gebied blijven verfijnen.

  4. Update je implementatieconfiguratie. Vercel handelt dit automatisch af, maar als je zelf host of een ander platform gebruikt, zul je je Dockerfile, bouw-scripts of serverless-configuratie moeten bijwerken.

Versie-specifieke noten voor 2026

Migratie Sleutelwijzigingen Geschatte inspanning (middelgrote app)
Next.js 14 → 15 Async request-API's, React 19, Turbopack stabiel 16-24 uur
Next.js 15 → 16 Bijgewerkte cache-standaards, React Compiler-integratie 8-16 uur

Als je nog Next.js 13 of eerder gebruikt, overweeg serieus of een gefaseerde migratie of een volledige herstart meer zin heeft. We helpen teams deze beslissing te nemen bij Social Animal. Soms is het eerlijke antwoord "begin opnieuw."

Prestatiebewaking als onderhoud

Onderhoud gaat niet alleen over het up-to-date houden van afhankelijkheden. Het gaat erom prestatieregressies op te vangen voordat je gebruikers (en Google) ze opmerken.

Wat je moet bewaken

  • Core Web Vitals: LCP, CLS, INP (Interaction to Next Paint verving FID in 2024). Gebruik Vercel Analytics, Google Search Console, of CrUX-gegevens.
  • Build-tijden: Als je build-tijd in drie maanden verdubbelt, klopt er iets niet. Volg het in CI.
  • Bundelgrootte: Stel budgetten in met @next/bundle-analyzer en size-limit.
  • Server-responstijden: Vooral voor Server Components en API-routes.
  • Foutsnelheden: Spikes na updates duiden op regressies.
# Voeg bundle-analyse toe aan je project
npm install @next/bundle-analyzer
// next.config.ts
import withBundleAnalyzer from '@next/bundle-analyzer'

const config = withBundleAnalyzer({
  enabled: process.env.ANALYZE === 'true',
})({
  // je configuratie
})

export default config

Voer ANALYZE=true npm run build maandelijks uit en vergelijk resultaten. Een geleidelijk groeiende bundelgrootte wijst vaak op een afhankelijkheid die veel gewicht in een minorbump heeft toegevoegd.

Wanneer opnieuw bouwen versus wanneer upgraden

Dit is de moeilijke vraag die niemand wil stellen. Dit is mijn besluitvormingskader:

Upgrade ter plaatse wanneer:

  • Je bent 1-2 grote versies achter
  • Je codebase volgt moderne patronen (App Router, Server Components)
  • Tests behandelen kritieke paden
  • Het team begrijpt de bestaande codebase

Overweeg opnieuw bouwen wanneer:

  • Je bent 3+ grote versies achter
  • De app staat nog steeds op Pages Router en je hebt App Router-functies nodig
  • Aanzienlijke technische schuld is opgehoopt buiten alleen afhankelijkheden
  • De originele architectuur past niet bij huidige vereisten

Overweeg migratie naar een ander framework wanneer:

  • Je site is meestal statisch en Next.js is overkill (kijk naar Astro)
  • Je vecht tegen Next.js-patronen in plaats van ermee te werken
  • Je team heeft expertise in een ander stack

Als je een contentrijke site met een headless CMS gebruikt, bespaart overschakelen naar een speciaal gebouwde architectuur soms meer tijd dan het onderhouden van een Next.js-app die voorbij de originele omvang is gegroeid. We discussiëren graag eerlijk over de opties.

Veelgestelde vragen

Hoe vaak moet ik Next.js-afhankelijkheden updaten? Patch-updates moeten wekelijks gebeuren. Ze zijn bijna altijd veilig en bevatten vaak beveiligingsreparaties. Minore updates maandelijks, nadat je de changelog hebt gelezen. Grote versies binnen 2-3 maanden na hun stabiele release, zodra het ecosysteem tijd heeft gehad om bij te werken. Langer dan 6 maanden wachten op grote versies creëert aanzienlijke upgrade-pijn.

Is het veilig om npm audit fix --force te gebruiken? Nee, niet zonder zorgvuldige beoordeling. De --force-vlag staat majorversion-bumps in afhankelijkheden toe, wat breaking changes kan introduceren. Ik gebruik het alleen als startpunt. Voer het uit op een branch, build, test grondig, en review elk wijziging in package-lock.json voor het samenvoegen. Voor productietoepassingen is handmatig bijwerken van het specifieke kwetsbare pakket bijna altijd veiliger.

Welk is het beste tool voor het automatiseren van Next.js-afhankelijkheidsupdates? Renovate Bot is mijn topkeuze voor 2026. Het handelt gegroepeerde updates af (houdt next, react, en react-dom in sync), ondersteunt automerge voor updates met laag risico, en heeft uitstekende monorepo-ondersteuning. Dependabot werkt prima voor eenvoudigere setups. Socket.dev is essentieel als extra laag voor supply chain-beveiliging, ongeacht welk update-tool je gebruikt.

Hoe ga ik om met beveiligingskwetsbaarheden in transitieve afhankelijkheden? Controleer eerst of het updaten van de directe afhankelijkheid die het kwetsbare pakket intrekt dit oplos. Zo niet, gebruik overrides in package.json (npm) of resolutions (yarn) om een specifieke versie af te dwingen. Als laatste redmiddel, als de kwetsbaarheid in een pakket zit dat je niet kunt updaten, evalueer of je de bovenliggende afhankelijkheid volledig kunt vervangen of een patch toevoegen met patch-package.

Moet ik naar de nieuwste Next.js-versie upgraden zodra deze wordt uitgebracht? Niet voor productie-apps. Wacht 2-4 weken na een grote release op de eerste ronde bugfixes. Volg de Next.js GitHub-problemen en de community op X/Twitter voor vroegrapportages van problemen. Voor minor- en patch-releases kun je agressiever zijn. Deze zijn meestal veilig binnen een paar dagen na release.

Hoe onderhoud ik een Next.js-app als ik een solo-ontwikkelaar ben? Automatisering is je beste vriend. Stel Renovate Bot in met automerge voor patch-updates, configureer CI om builds en tests uit te voeren op elke afhankelijkheid PR, en zet een vast 2-uurblok maandelijks opzij voor handmatige beoordeling. Het schema dat ik heb beschreven schaalt goed omlaag. De wekelijkse controle wordt een 15-minuten blik op geautomatiseerde PRs, en de maandelijkse diepe duik blijft op 2 uur.

Welke Node.js-versie moet ik gebruiken met Next.js in 2026? Next.js 16 vereist Node.js 18.18 of hoger, maar ik zou aanraden om Node.js 22 LTS uit te voeren (wat in oktober 2024 LTS-status kreeg en wordt ondersteund tot april 2027). Node.js 20 LTS is ook prima. Vermijd Node.js 18 tenzij je een specifieke compatibiliteitsvereiste hebt. Het bereikte einde van levensduur in april 2025 en zou niet meer in productie moeten zitten.

Is het de moeite waard om voor professioneel onderhoud te betalen als we interne ontwikkelaars hebben? Dat hangt af van de bandbreedte en expertise van je team. Interne ontwikkelaars stellen onderhoud vaak uit omdat featurework altijd urgenter voelt. Als je Next.js-app bedrijfskritiek is en je merkt dat onderhoud consequent wordt uitgesteld, een speciaal onderhoudsakkoord met een gespecialiseerd team zorgt ervoor dat het echt gebeurt. We hebben veel teams gezien waar de kosten van uitgesteld onderhoud ver de kosten van regelmatige professionele zorg oversteeg. Klaar om uit te stellen te stoppen? Krijg een voorstel in 48 uur en laten we bepalen wat je app nodig heeft.