Turbopack in Next.js 16: Migratie van Webpack, Setup en Productie Builds
Turbopack is sinds Next.js 16 de standaardbundler voor dev en build. Deze gids toont hoe je vanaf Webpack migreert: loader-conversie, plugin-alternatieven, persistent caching in 16.3 en monorepo-integratie met concrete config-snippets en benchmark-cijfers.
Turbopack is de Rust-gebaseerde bundler van Vercel die sinds Next.js 16 (oktober 2025) standaard next dev én next build aandrijft. Je hoeft niets te configureren om hem aan te zetten, maar bij een migratie vanaf Webpack heb je vier dingen nodig: verwijder custom webpack-plugins, hertaal next.config.js-loaders naar de turbopack.rules-syntax, schakel turbopackFileSystemCacheForBuild in voor snelle CI-builds, en meet je bundle-sizes voor en na. Deze gids loopt door dat migratiepad heen, laat zien wat er in Next.js 16.3 stabiel is geworden, en geeft de commando's en config-snippets die je vandaag in productie kunt draaien.
Turbopack is sinds Next.js 16 (oktober 2025) de standaardbundler voor zowel next dev als next build; de --turbopack-flag is niet meer nodig.
Webpack-loaders werken via turbopack.rules, maar Webpack-plugins zijn niet compatibel. Dat is de #1 blocker bij een migratie.
Sinds Next.js 16.1 is filesystem-caching voor dev stabiel; sinds 16.3 kun je met turbopackFileSystemCacheForBuild ook productiebuilds cachen tussen CI-runs.
Vercel meet 76% snellere cold-starts en tot 90% lager dev-server geheugengebruik in 16.3 dankzij memory eviction.
Migreren van een grote codebase kan tijdelijk bundle-sizes vergroten (Cal.com zag +72% first-load JS); benchmark elke route na de switch.
Voor legacy-projecten met kritieke Webpack-plugins gebruik je next build --webpack als opt-out totdat Turbopack het equivalent ondersteunt.
Wat is Turbopack en waarom vervangt het Webpack?
Turbopack is de opvolger van Webpack die Vercel sinds 2022 in Rust bouwt, met hetzelfde mentale model (modules, loaders, plugins), maar met een incrementele compute-engine die alleen hercompileert wat daadwerkelijk is veranderd. In mijn ervaring als iemand die de build-pipeline van een SaaS onderhoudt, is die incrementaliteit belangrijker dan de brute snelheid: Webpack's grootste probleem was nooit "koude start duurt 30 seconden", het was "als ik één string in één component wijzig, wacht ik 4 seconden op HMR". Turbopack lost dat op door de dependency-graph als een deterministische functie te modelleren, waarvan de output op file-hash niveau gecached wordt.
De concrete winst zit in drie plaatsen. Ten eerste dev-server startup: Vercel's eigen benchmarks tonen tot 76% snellere cold starts vergeleken met Webpack, en op mid-range machines zijn dev-servers die eerder 25–45 seconden opstartten nu in 4–8 seconden bereikbaar. Ten tweede HMR-latency op grote codebases (>10.000 modules) — dit is waar de "700x sneller" marketingcijfers vandaan komen, hoewel ze een geïsoleerd micro-benchmark zijn en geen real-world app. Ten derde geheugengebruik: sinds Next.js 16.3 evict Turbopack ongebruikte compilatieresultaten uit RAM, wat volgens Vercel tot 90% lagere geheugendruk oplevert op lange dev-sessies. Voor teams die dagenlang dezelfde next dev-instance draaien is dat het verschil tussen wel of niet je machine herstarten voor de lunch.
Turbopack vs Webpack: prestatievergelijking
Voordat je aan een migratie begint, is het de moeite waard om te begrijpen op welke assen Turbopack wint, verliest of gelijk blijft. Onder een bepaalde codebase-grootte is het verschil marginaal. Voor apps met minder dan ~1000 modules levert de switch weinig meetbaar voordeel op behalve consistentie met de rest van het ecosysteem. Boven de 10.000 modules verandert het echter volledig het karakter van de development-loop.
Eigenschap
Webpack (Next.js 15 en ouder)
Turbopack (Next.js 16+)
Cold dev start (10K+ modules)
25–45s
4–8s
HMR update
1–5s
50–300ms
Productie build stabiliteit
Volledig stabiel, jaren geoptimaliseerd
Stabiel sinds 16.0, cache stabiel sinds 16.3
Webpack-loaders
Native
Ondersteund via turbopack.rules
Webpack-plugins
Native
Niet ondersteund
Persistent build cache
Ingebouwd (webpack 5)
Opt-in via turbopackFileSystemCacheForBuild
Bundle-size (tree shaking)
Meestal iets kleiner
Grotere client chunks in edge cases
Geheugengebruik dev-server
Groeit monotoon per gebruikte route
Evict cache sinds 16.3
De belangrijkste asterisk zit in de bundle-size rij. Cal.com's publieke migratie-postmortem toonde 19% snellere builds, maar +72% mediaan first-load JS door duplicatie van libraries als react-dropzone in elf verschillende bundles. Dat is niet fundamenteel; het is een klasse van code-splitting bugs die Vercel actief aan het dichten is. Maar het betekent wel dat je na de switch elke publieke route moet meten met @next/bundle-analyzer voordat je uitrolt. Meer over meten in het test-artikel over Vitest en Playwright, waar performance regressie-tests goed samengaan met bundle-controles in CI.
Migratie: van Webpack-config naar Turbopack in Next.js 16
Als je een greenfield project op Next.js 16 start, heb je nul migratiewerk; Turbopack draait vanaf de eerste npx create-next-app. De interessante situatie is een bestaand project op Next.js 14 of 15 met een niet-triviale next.config.js. Voor die groep is dit de volgorde die ik aanraad, in exact deze volgorde.
Stap 1: Upgrade naar Next.js 16 (met Webpack blijven)
Zet eerst alleen de framework-upgrade in productie, zonder Turbopack aan te zetten. Dat isoleert de risico's, want je weet dan zeker dat een crash niet aan Turbopack ligt, maar aan bijvoorbeeld de async request-APIs of gewijzigde caching-defaults.
npx @next/codemod@canary upgrade latest
# Draai tests, deploy naar staging, controleer telemetrie een week lang.
# Zet dan pas Turbopack aan.
Stap 2: Inventariseer je huidige webpack-configuratie
Open next.config.js en categoriseer elk stuk custom logica in drie bakjes: loaders (bijv. SVGR, MDX, YAML), plugins (bijv. DefinePlugin, custom BannerPlugin, bundle-analyzer) en resolve-aliassen. Alleen loaders en aliassen zijn triviaal te migreren. Plugins zijn de blocker: voor elke plugin moet je een alternatief vinden of tijdelijk de opt-out gebruiken.
Stap 3: Migreer loaders naar de turbopack.rules-syntax
Belangrijk: je kunt geen webpack()-callback en een turbopack-block tegelijk hebben. Dat is een harde build-error sinds 16.0. Je kiest één van beide runtimes per config, en gebruikt CLI-flags om te wisselen tijdens de overgangsperiode.
Stap 4: Test dev-server, dan productiebuild
# Dev-server (default in 16+)
npx next dev
# Expliciete opt-out naar Webpack als iets breekt
npx next dev --webpack
# Productiebuild met persistent cache
npx next build
# Bundle inspecteren
ANALYZE=true npx next build
Webpack loaders en plugins: wat werkt en wat breekt
De onvermijdelijke vraag bij elk staff-eng gesprek: "Werken onze bestaande webpack loaders?" Kort antwoord: loaders ja, plugins nee. Het lange antwoord vereist onderscheid tussen drie categorieën die veel teams in één zin gooien.
Loaders zijn per-file transformers (SVGR, MDX-loader, YAML-loader, raw-loader, babel-loader), hoewel je die laatste vervangt door SWC. Deze werken één op één via turbopack.rules, met de kanttekening dat de loader zelf idempotent en synchrone moet zijn; loaders die de globale Webpack context lezen zullen falen. In de praktijk migreren 90% van de loaders zonder aanpassing.
Plugins hooken in de Webpack compilation lifecycle en hebben geen 1-op-1 Turbopack API. De veelvoorkomende cases:
DefinePlugin: vervang door env in next.config.js, of gewoon process.env.NEXT_PUBLIC_* variabelen.
BannerPlugin voor licentie-headers: draai dat als een post-build script.
@next/bundle-analyzer: sinds 16.1 heeft Next.js een ingebouwde Turbopack-compatible variant. Gebruik ANALYZE=true next build.
SentryWebpackPlugin: vervang door @sentry/nextjs v9+, die met Turbopack werkt via source-map upload post-build.
Module Federation: nog geen Turbopack-support. Staat op de publieke roadmap, maar is de #1 reden om nog op Webpack te blijven als je een micro-frontend architectuur hebt.
Aliassen en resolve-config zijn triviaal: turbopack.resolveAlias en turbopack.resolveExtensions dekken bijna alles. Interne @/components-aliassen die via tsconfig.json paths werken, worden automatisch geïnterpreteerd; je hoeft ze niet te dupliceren in de bundler-config.
Productiebuilds en persistent caching in 16.3
De grootste kritiek op vroege Turbopack-productiebuilds was dat ze niet incrementeel waren: elke CI-run begon fris, terwijl Webpack 5's ingebouwde persistent cache al jaren de tweede build kon halveren. Next.js 16.3 sluit die gap met turbopackFileSystemCacheForBuild, een opt-in flag die de compilatie-artefacten naar disk schrijft:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
// Cache voor productiebuilds (opt-in in 16.3, wordt default in 16.4)
turbopackFileSystemCacheForBuild: true,
// Cache voor dev is al default sinds 16.1
// turbopackFileSystemCacheForDev: true,
},
};
module.exports = nextConfig;
De cache wordt opgeslagen in .next/cache/turbopack. Om er iets aan te hebben in CI moet je die directory tussen runs bewaren, hetzelfde patroon als de bestaande node_modules-cache. Voor GitHub Actions ziet dat er zo uit:
Met deze setup zag mijn eigen productieproject een tweede-build tijd van 3m40s naar 48s dalen — een 78% winst op incrementele PR-builds. Belangrijke waarschuwing: er is een bekend GitHub-discussion issue #87283, waar corrupte cache-entries de dev-server in een "Ready but wedged" toestand kunnen brengen. Bouw dus altijd een rm -rf .next/cache-fallback in je CI-workflow, voor het geval de cache verlopen is.
Voor advies over hoe deze buildwinst zich verhoudt tot runtime caching (data cache, revalidatie), zie de Data Cache en use cache-gids. De twee cache-lagen werken orthogonaal.
Turbopack in een monorepo met Turborepo
Voor teams die pnpm workspaces of Turborepo gebruiken, is er één detail dat het waard is om vooraf te kennen: Turbopack's incrementele engine begrijpt symlinked packages nu wel correct sinds 16.2, maar de transpilePackages-optie is nog steeds nodig als je uncompiled TypeScript vanuit een intern package importeert.
De echte winst in monorepo-context is dat Turbopack's per-module cache samenwerkt met Turborepo's remote cache. Als je een gedeeld @myorg/ui package niet wijzigt tussen builds, deelt Turborepo de compilatie-output tussen developers, en gebruikt Turbopack diezelfde output als input. Dat betekent dat een nieuw teamlid dat een branch checkout (waar traditioneel 5 minuten cold-build op stond) nu in 20–40 seconden een werkende dev-server heeft. Voor rendering-overwegingen binnen zo'n multi-app opzet is de rendering-strategieën gids een goed vervolg.
Turbopack debuggen en veelvoorkomende problemen
In productie draai je zelden een debugger; je leest logs en foutmeldingen. Dit zijn de vier problemen die ik het vaakst zie in code-reviews en post-mortems sinds de Turbopack-switch:
1. "Module not found" die onder Webpack wél werkte
Turbopack is strikter over case-sensitivity en over impliciete extensies. import Foo from './foo' waar het bestand Foo.tsx heet, werkt op macOS onder Webpack (case-insensitive filesystem), maar breekt onder Turbopack. Los op door bestandsnamen consistent te maken en expliciete extensies in je editor-config te forceren. Ik liep hier zelf tegenaan bij het shippen van een grote refactor; het is dat soort bug dat lokaal onvindbaar is en pas in CI opduikt.
2. Onverklaarbaar grote client bundles
Bij twijfel: draai ANALYZE=true npx next build. Kijk naar shared chunks. Als je een third-party library (zoals date-fns of lodash) in meerdere route-bundles ziet duiken, is dat een code-splitting regressie. De workaround is optimizePackageImports in next.config.js:
3. Cache-corruptie na een Node.js of package upgrade
Nieuwe Node-versies of grote dependency-upgrades kunnen de cache invalideren op een manier die niet altijd correct wordt gedetecteerd. Standaard oplossing: rm -rf .next en herbouw. Als je dit vaker dan één keer per week doet, escaleer het als bug via next info output.
4. HMR die niet triggert op bepaalde files
Meestal een symlink-issue in monorepo's, of een file-watcher die de OS-limiet raakt. Op Linux verhoog je fs.inotify.max_user_watches. Op macOS geen probleem; op Windows overweeg WSL2 als je een grote codebase hebt.
Veelgestelde vragen
Is Turbopack sneller dan Webpack voor productie builds?
Voor cold builds op grote codebases: ja, tot 40–60% sneller. Voor incrementele builds met persistent caching aan (sinds 16.3) is de winst dramatisch, met 70%+ tijdreductie tussen opeenvolgende CI-runs. Op kleine apps (<1000 modules) is het verschil verwaarloosbaar.
Kan ik Webpack plugins gebruiken met Turbopack?
Nee, Turbopack ondersteunt geen Webpack-plugins. Loaders werken wel via de turbopack.rules-syntax, maar plugins die in de Webpack compilation lifecycle hooken vereisen een alternatief of tijdelijke opt-out via next build --webpack.
Hoe schakel ik Turbopack uit als ik problemen heb?
Gebruik de --webpack-flag: next dev --webpack of next build --webpack. Verwijder ook eventuele turbopack-configuratie uit next.config.js en herstel je oorspronkelijke webpack()-callback. Dit is expliciet ondersteund door Vercel als migratiestrategie.
Wat is het verschil tussen Turbopack en SWC?
SWC is de Rust-gebaseerde transpiler (Babel-vervanger) die per-file JavaScript en TypeScript naar browser-code compileert. Turbopack is de bundler die het geheel aan elkaar knoopt: module resolution, tree-shaking, code-splitting. Turbopack gebruikt SWC intern voor de transpilatie-stap.
Werkt Turbopack met MDX, SVGR en andere veelgebruikte tooling?
Ja. MDX werkt via @next/mdx zonder extra configuratie. SVGR en YAML werken via turbopack.rules. Bundle-analyzer heeft sinds Next.js 16.1 een ingebouwde Turbopack-compatible modus. Sentry werkt via @sentry/nextjs v9+.
Werkende Docker-setup voor Next.js 15 en 16 met standalone output, multi-stage Dockerfile, sharp voor Image Optimization en een compleet migratieplan van Vercel in 3 tot 5 dagen.
Zet streaming, Suspense en progressive rendering in de Next.js App Router (versie 15 en 16) in de praktijk. Met loading.tsx patronen, meerdere boundaries per pagina, useSearchParams CSR-bailout fix en before/after DevTools traces die 40-70% LCP-winst laten zien.