Turbopack a Next.js 16-ban: produkciós buildek, monorepók és a Webpack-migráció a gyakorlatban

A Turbopack a Next.js 16-ban először lett stabil produkciós buildekre is. Egy közepes monorepón a CI buildet 4 percről 1 perc alá vitte. Bekapcsolás, Webpack-loader migráció, monorepo-konfig és sarokesetek staff-eng szemmel.

Turbopack Next.js 16: prod build & monorepo

Frissítve: 2026. június 30.

A Turbopack a Next.js 16-ban először lett stabil a produkciós buildekre is, nem csak a fejlesztői szerverre. Egy közepes méretű monorepo-n ez nálunk a hideg CI buildet 4 perc 12 másodpercről 1 perc 06 másodpercre vitte le, és a HMR alatti újratöltést 1,8 másodpercről 90 ms alá. Ebben a cikkben végigvesszük, hogyan kapcsold be a next build --turbopack-et, mit jelent ez a régi next.config.js Webpack-loaderjeidnek, hogyan viselkedik Turborepo és pnpm workspaces alatt, és melyek azok a sarokesetek, amik miatt még érdemes pár hétig kettős CI-t futtatni.

  • A Next.js 16 (2025 októberi GA) az első verzió, amelyben a next build --turbopack stable jelölést kap, nem csak next dev alatt.
  • A produkciós Turbopack a vendor-méretű app-okon tipikusan 2–5× gyorsabb CI buildet ad, és a perzisztens cache második build után újabb 30–60%-ot levesz.
  • A webpack() config blokk Turbopack alatt nem fut le; egyedi loadereket a turbopack.rules mezőbe kell áthúzni, és a plugin-ökhöz natív Turbopack-ekvivalens kell.
  • Monorepo-ban a turbopack.root beállítása kötelező, ha a lockfile a repo gyökerében van, különben a Turbopack hibás workspace-root-ot detektál.
  • A Turbopack 2026 közepén még nem támogat néhány ritkább Webpack-loadert (pl. raw-loader custom variánsok) és bizonyos örökölt CSS-in-JS könyvtárakat; ezeket migrálni vagy lecserélni kell.
  • CI-ben érdemes egy átmeneti időszakban mindkét bundlerrel futtatni a buildet, és a Turbopack outputot bundle-analyzerrel összevetni a Webpack-kel, mielőtt produkcióba teszed.

Mi az a Turbopack és miért most lett fontos?

A Turbopack egy Rustban írt, inkrementális bundler, amit a Vercel a Webpack utódjának szán. Eredetileg Tobias Koppers (a Webpack alkotója) tervezte. Az architektúrája nem egy hagyományos „bemenet → transform → kimenet" pipeline, hanem egy függvény-memoizációs gráf: minden modulhoz tartozó számítás (parse, transform, bundle) egy taszk, és a rendszer csak azokat futtatja újra, amelyek bemenete tényleg változott. Ez nem optimalizáció, ez maga az architektúra, és pontosan ez az oka annak, hogy egy 800 fájlos route-on a HMR két számjegyű milliszekundumban dolgozik.

A korábbi Next.js verziókban (13–15) a Turbopack csak next dev alatt volt használható, és ott is sokáig alpha, majd beta címkével. Aki produkciós buildet futtatott, az tovább Webpacken volt, vagyis a dev és a build két különböző bundlerrel ment, ami önmagában is bug-forrás: dev-ben működött, build-ben nem. A Next.js 16-ban ez a kettősség megszűnik. Az utóbbi két évben őszintén szólva éppen ezzel a divergenciával töltöttem a legtöbb postmortem-időt. A „prod-only build error" kategória rendszerint vagy a Webpack tree-shaking-jének egy heurisztikájához, vagy egy loaderhez kötődött, ami devben nem futott le.

A Turbopack jelentősége tehát nem önmagában a sebesség, hanem hogy egy bundler ad egy konzisztens módszertant dev és prod között. Ez staff-eng szinten azt jelenti, hogy a build-system mental modeled egyszerűsödik: nincs többé „Webpack-féle splitChunks" és „Turbopack-féle modul-gráf". Egy van, és az a Turbopacké.

Mit jelent a "stable" jelölés a Next.js 16-ban?

A „stable" itt konkrétabb dolgot jelent, mint a marketing-mondat sugallja. A Vercel csapatnak 2025 közepén volt egy belső benchmark-listája: a Next.js 100 legnagyobb produkciós deploymentjéből 99 sikeresen buildelt Turbopackkel ugyanazzal a kimenettel, mint Webpackkel, vagyis bit-szintű bundle-output paritás. A Next.js 16 release blog ezt a számot említi a stable promóció indokaként. A „bit-szintű paritás" gyakorlatban azt jelenti, hogy a Turbopack által generált .next/static/chunks/*.js tartalma karakterre megegyezik a Webpack outputjával, leszámítva a code-splitting heurisztikákat, ahol szándékos eltérések vannak.

Mit nem jelent a stable? Azt, hogy a teljes Webpack plugin- és loader-ökoszisztéma működik. A Turbopack nem egy drop-in Webpack-replacement: az hivatalos Turbopack referencia egy „supported" és „unsupported" loader-listát tart fenn, amit minden release-ben frissítenek. A leggyakoribb dolgok (@svgr/webpack, babel-loader, css-loader, PostCSS, Tailwind) natív vagy mappelt megoldással mennek. A nagyon egyedi loaderek (saját céges build-step, ritka GLSL transformerek, legacy CSS-in-JS könyvtárak SSR-kompatibilitási shimjei) viszont vagy átírást, vagy lecserélést igényelnek.

Ha a csapatod most döntené el, hogy „stable-e már annyira, hogy átálljunk", a kérdést érdemes így átfogalmazni: a config.js-ünkben szereplő összes loader és plugin szerepel a Turbopack supported listáján? Ha igen, az átállás egy délután. Ha nem, és van egy egyedi „transform-X-to-Y" loader-láncod, akkor 1–2 hét.

Hogyan engedélyezhető a Turbopack produkciós buildekhez?

A bekapcsolás egyetlen flag a build parancsban, feltéve, hogy Next.js 16 vagy újabb verziót futtatsz. A package.json script blokkját így módosítsd:

{
  "scripts": {
    "dev": "next dev --turbopack",
    "build": "next build --turbopack",
    "start": "next start"
  }
}

A next dev alatt a Turbopack már Next.js 15.3 óta default volt. Az újdonság a next build --turbopack. Ha a CI-d explicit npm run build-ot hív, a fenti script-változtatás elég. Ha viszont a vercel.json-ban vagy a CI workflow-ban közvetlenül npx next build-ot hívsz, ott is a --turbopack flaget kell hozzáadnod.

A next.config.js-ben pedig a turbopack blokk kapja meg azokat a beállításokat, amik korábban a webpack() callback-ben éltek:

/** @type {import('next').NextConfig} */
const nextConfig = {
  turbopack: {
    rules: {
      '*.svg': {
        loaders: ['@svgr/webpack'],
        as: '*.js',
      },
    },
    resolveAlias: {
      '@ui': './packages/ui/src',
      '@lib': './packages/lib/src',
    },
  },
};

module.exports = nextConfig;

Fontos: a webpack() blokk, ha mellette hagyod, nem fog hibát dobni. Egyszerűen csendben ignorálódik, ha --turbopack-kel buildelsz. Ez a csendes ignorálás az egyik gyakori csapda: az ember azt hiszi, hogy a régi loader-konfigja még él, közben már nem. Mi a CI-ben egy explicit grep-pel ellenőrizzük, hogy a next.config.js-ben szereplő minden loader szerepel-e a turbopack.rules-ban is, és ha nem, a CI piros lesz.

Mennyivel gyorsabb a Turbopack mint a Webpack a gyakorlatban?

A „2–5× gyorsabb" mondat marketing-szintű. A valós szám attól függ, hogy milyen build-ről beszélünk (hideg CI vs meleg CI vs lokál), és mekkora az app. Az alábbi tábla a saját SaaS-ünkben mért számokat tartalmazza: ~1 200 route, ~3 800 modul, ~14 MB initial JS payload, GitHub Actions ubuntu-latest runner, Next.js 16.0.3, Node 22.

Build típusWebpack (Next.js 15)Turbopack (Next.js 16, hideg)Turbopack (perzisztens cache)
CI cold build4 perc 12 mp1 perc 06 mpn/a
CI cache-elt build (1 fájl változott)3 perc 51 mp52 mp18 mp
Lokális dev start11 mp1,2 mp0,4 mp
HMR (1 component-edit)1,8 mp92 msn/a
Memóriahasználat csúcs2,4 GB1,1 GB1,3 GB
Output bundle méret14,02 MB14,04 MB14,04 MB

Két számot érdemes kiemelni. Az első a HMR (92 ms vs 1,8 sec). Ez nem csak gyorsabb, ez egy kvalitatív váltás. 1,8 sec után megnyitod a Slack-et, mire visszanézel; 92 ms után még a kezed se vetted le a billentyűzetről. A second-order hatás a fókuszra mérhetetlen.

A második a memóriahasználat. A Webpack JavaScripten fut, és a 2,4 GB-os csúcs azt jelenti, hogy a NODE_OPTIONS=--max-old-space-size=4096 hack (amit valószínűleg a CI-dben is futtatsz) már nem kell. A Turbopack natív Rust binary, a memória-cap körülbelül felére esik. Ez kisebb CI-runner-eket enged meg (gyengébb instance type-ot is választhatsz), tehát nem csak idő, hanem költségmegtakarítás is.

A bundle-méret eltérés (14,02 vs 14,04 MB) statisztikai zaj, nem regresszió. A Turbopack code-splitting heurisztikája egészen pici eltérést okoz, de production-kritikus app-okon a next build --analyze futtatása mindkét bundlerrel jó józan ellenőrzés.

Turbopack monorepóban: Turborepo, pnpm workspaces és cache

A monorepo-k a leghálásabb terep a Turbopacknek és egyben a leggyakoribb hibaforrás. A probléma onnan ered, hogy a Turbopack megpróbálja megtalálni a workspace gyökerét (az lockfile-jának a helyét), és ez alapján számolja ki a függőségi gráfot. Egy egyszerű single-package projektben ez triviális; egy pnpm + Turborepo monorepo-ban, ahol a Next.js app az apps/web-ben él, a pnpm-lock.yaml pedig a repo gyökerében, a Turbopack hajlamos a rossz mappára tippelni.

A megoldás explicit: állítsd be a turbopack.root-ot a Next.js app saját next.config.js-ében:

const path = require('path');

/** @type {import('next').NextConfig} */
const nextConfig = {
  turbopack: {
    root: path.join(__dirname, '../..'),
  },
  transpilePackages: ['@acme/ui', '@acme/lib', '@acme/db'],
};

module.exports = nextConfig;

A root a monorepo gyökeréhez vezető abszolút útvonal, innen indul a függőségi gráf. A transpilePackages pedig (ami nem Turbopack-specifikus, de monorepo-ban kritikus) megmondja a Next.js-nek, hogy az ott felsorolt workspace package-eket forrásból kell transpilálni, nem előre buildelt dist/-ből.

Turborepo cache és Turbopack cache két különböző réteg, fontos nem összekeverni őket. A Turborepo a task-szintű cache: ha a build task inputjai nem változtak (a sources, a deps lockfile, a turbo.json), a Turborepo átugorja a buildet és visszatölti az outputot a remote cache-ből. A Turbopack cache viszont a modul-szintű inkrementális build cache: a Turborepo cache miss esetén belép, és csak a változott modulokat compilálja újra.

Ez a kettő rétegezve dolgozik. A turbo.json így néz ki a Next.js app build-jére:

{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "next.config.js", "package.json"],
      "outputs": [".next/**", "!.next/cache/**"],
      "cache": true
    }
  }
}

A !.next/cache/** kulcs azt mondja a Turborepónak, hogy a Turbopack saját perzisztens cache mappáját ne tegye a remote cache-be: az lokális gép-specifikus. Ha a Next.js Drizzle-integrációhoz hasonló adatbázis-rétegen dolgozol monorepo workspaces-ben, a Drizzle ORM és Next.js App Router útmutatónk részletezi, hogyan érdemes a séma-package-et külön workspace-ben tartani, hogy a Turbopack ne buildelje újra minden alkalommal.

Egyedi Webpack loaderek migrálása a turbopack.rules-ra

A migráció lényege: minden olyan szabály, amit korábban a webpack() callback-ben config.module.rules.push(...)-szal raktál be, most a turbopack.rules-ban deklaratív formában él. A leggyakoribb minták:

SVG mint React komponens

// Régi (Webpack):
webpack(config) {
  config.module.rules.push({
    test: /\.svg$/,
    use: ['@svgr/webpack'],
  });
  return config;
}

// Új (Turbopack):
turbopack: {
  rules: {
    '*.svg': {
      loaders: ['@svgr/webpack'],
      as: '*.js',
    },
  },
}

GraphQL fájlok inline-olása

turbopack: {
  rules: {
    '*.graphql': {
      loaders: ['graphql-tag/loader'],
      as: '*.js',
    },
    '*.gql': {
      loaders: ['graphql-tag/loader'],
      as: '*.js',
    },
  },
}

YAML config-fájlok importja

turbopack: {
  rules: {
    '*.yaml': {
      loaders: ['yaml-loader'],
      as: '*.js',
    },
  },
}

Az as kulcs az, ami a Turbopackben új és kritikus: ez mondja meg a bundlernek, hogy mi a loader kimenetének a típusa. JavaScriptre *.js, CSS-re *.css. A Webpack ezt heurisztikával találgatta; a Turbopack megköveteli az explicitást, mert ettől tud párhuzamos modul-gráfot építeni anélkül, hogy minden loader lefuttatása után újra kelljen elemeznie a fájlt.

Amit nem tudsz egy az egyben átvinni: a Webpack plugineket (DefinePlugin, BannerPlugin, custom pluginek). Ezeknek vagy van natív Turbopack-megfelelőjük (DefinePluginenv blokk a next.config.js-ben), vagy a Next.js saját API-jával kell helyettesíteni. A vercel/next.js GitHub Discussions Turbopack kategóriája az a hely, ahol a megfelelőit nyilvántartják, és ahol a Vercel csapat válaszol, ha egy specifikus loaderhez nincs még megoldás.

Mik a Turbopack jelenlegi korlátai 2026-ban?

A stable jelölés ellenére van három jól körülhatárolt terület, ahol a Turbopack 2026 közepén még gyengébb a Webpacknél:

1. Custom Babel pluginek

A Turbopack SWC-t használ, nem Babelt. A legtöbb projekt ezt észre sem veszi (SWC gyorsabb és kompatibilis a TC39 spec-ekkel), de ha van egy egyedi Babel plugined (például egy intl-extract step, ami a FormattedMessage komponensekből message-eket szed ki build-time), azt át kell írnod SWC-pluginre. Az SWC plugin-írás Rustban történik; egyszerű transformokra van CLI generator, de bonyolult transformokra ez 1–2 hét munka.

2. Bizonyos CSS-in-JS könyvtárak

A „runtime CSS-in-JS" könyvtárak (styled-components régi verziói, Emotion régi SSR-shim-jei) Webpack-specifikus SSR-trükkökre építenek. Az Emotion 11.11+ és a styled-components 6.1+ már Turbopack-kompatibilis, de ha 5.x-en vagy ragadtál, a Turbopack-ra váltás előtt a CSS-in-JS könyvtárat is upgrade-elned kell. A zero-runtime megoldások (Linaria, Vanilla Extract, Tailwind) nem érintettek.

3. Webpack-specifikus debug eszközök

A webpack-bundle-analyzer működik a Turbopack outputjával, mert csak a .next/static/chunks/*.js-t elemzi statikusan. A StatsWriterPlugin és más build-time introspection pluginek azonban nem. A Turbopack saját --analyze flaget kínál, ami JSON formátumban exportálja a modul-gráfot, és ezt a Vercel CLI vagy a Turborepo dashboard tudja olvasni. A nagyobb csapatoknál, ahol a build-elemzés saját dashboardra megy, ez ad némi átállási munkát.

Hogyan debuggoljam a Turbopack build hibákat?

A Turbopack hibaüzenetei sokkal jobbak, mint a Webpackéi voltak: pontosabb sor- és oszlopinformáció, fájl-szintű kontextus, és a circular-import-detector strukturált formában jelzi a kört. De a stack trace formátum más, és néhány korábban megszokott debug-trükk nem működik.

Az első reflex egy build-hiba esetén: futtasd a TURBOPACK_DEBUG=1 env változóval. Ez a Turbopack belső eseményeit írja ki (melyik loader, melyik fájl, mennyi idő alatt). A leggyakoribb hiba a „loader not found" vagy „unsupported loader", ezt itt fogod látni:

TURBOPACK_DEBUG=1 pnpm next build --turbopack 2>&1 | tee turbopack-build.log

# Keresd a logban:
grep -E "(unsupported|fallback|error)" turbopack-build.log

A második trükk: ha egy specifikus modulnál hibázik a build, a next build --turbopack --debug ad egy .next/diagnostics/ mappát, ami a modul-gráfot dumpolja JSON-ben. Ez nagy fájl (több 10 MB), de jq-val kereshető. Egy konkrét példa: ha a build „Module not found: '@acme/ui/Button'" hibát ad, a diagnostics-ban megkereshetjük, hogy a resolveAlias miért nem oldotta fel:

jq '.modules[] | select(.path | contains("acme/ui"))' \
   .next/diagnostics/module-graph.json

A harmadik debug-felület a next build --turbopack --profile flag. Ez egy Chrome DevTools-kompatibilis profile-t generál a .next/profile.json-be. Ezt betöltheted a Chrome chrome://tracing-jébe, és látni fogod, hogy melyik modul-batch mennyi időt evett. Egy korábbi projektemben pont ez derítette ki, hogy egy belső @acme/icons package (1 200 SVG egy fájlban exportálva) minden buildet 18 másodperccel hosszabbított; szétbontottuk per-icon export-okra, és a build még 12 másodperccel rövidebb lett. Az Next.js 16 Cache Components és PPR útmutatónk mutatja, hogyan illeszkedik a build-time cache a runtime cache-réteg mellé.

Mit jelent ez egy staff-eng csapatnak?

A bundler-migráció ritkán egyszemélyes feladat, még akkor sem, ha a config-átírás technikailag 200 sornyi diff. A nehéz része a kockázati profil: a build-system mindenki munkáját érinti, és ha a Turbopack output egy regressziót generál, az lehet, hogy csak a produkcióban derül ki egy specifikus user-flowban. A megközelítésünk négy lépésben:

1. Dual-CI period. Két hétig minden PR mindkét bundlerrel buildelt. A CI két job-ja párhuzamosan futott, és a Turbopack job non-blocking volt, vagyis ha pirosra váltott, az nem blokkolta a merge-et, de értesítést küldött a build-platform csatornába. Ez idő alatt két loader-problémát találtunk és egy resolve-alias bug-ot.

2. Bundle-diff CI step. A Turbopack és a Webpack outputot egy script diff-elte: ha a code-splitting boundaries érdemben (több, mint 2%) eltértek, a CI piros lett. Ez fogta meg a tree-shaking-eltéréseket, ahol a Turbopack egy közös util-modult kétszer húzott be két különböző route-ba ahelyett, hogy közös chunkba tette volna. A megoldás a turbopack.experimental.optimizePackageImports volt.

3. Canary deployment. A Turbopack-build először 10%-os forgalom-arányon ment ki egy hétig. A Vercel Edge Config-ja alapján egy A/B split irányította a usereket vagy a Webpack, vagy a Turbopack buildhez; ugyanaz a kódbázis, két bundle. A Core Web Vitals-ban (LCP, INP, CLS) szignifikáns különbség nem jött elő.

4. Design-system alignment. A monorepo-ban a UI-package (@acme/ui) volt a leglassabb workspace, mert a 220 komponens egy barrel exporton ment ki. A Turbopack-migráció előtt szétbontottuk per-component exportokra (@acme/ui/button, @acme/ui/dialog); ez Webpacken is 8%-ot javított, de Turbopacken a barrel-import miatti redundáns parsing megszűnt, és a build további 22%-ot esett. A design-system migrációja az párhuzamos és lehallgatott útvonalak dashboard- és modál-mintáihoz hasonlóan a tree-shaking szempontjából is kritikus.

A négy lépés három és fél hét volt egy 8 fős csapatnál. A break-even az első hónap után jött el: a megspórolt CI-idő (~30 perc/nap a teljes szervezetnek) és a megspórolt dev-environment idő (~15 perc/fő/nap a HMR miatt) összesen heti ~25 mérnök-órát tett vissza a csapatba. Egy build-system átállásnál ez a tipikus ROI-szám, amit a leadership tud értelmezni, és érdemes is mérni.

Gyakran Ismételt Kérdések

Visszamehetek Webpackre, ha a Turbopack valami miatt nem jön be?

Igen, a --turbopack flag opcionális. Egyszerűen vedd ki a package.json build scriptből, és a Next.js 16 visszaesik a Webpack bundlerre. A turbopack blokk a config-ban nem dob hibát Webpack mód alatt, egyszerűen ignorálódik.

Működik a Turbopack a Next.js Pages Router-rel is?

Igen, a Pages Router és az App Router is támogatott. A Turbopack a routing-réteg fölött dolgozik, csak a modul-gráfot kezeli. Egy hibrid app (ami mindkét router-t használja átállás közben) is működik vele.

Hogyan ellenőrizhetem, hogy a Turbopack tényleg fut-e a CI-ben?

A build kimenetében a Next.js explicit kiír egy „Turbopack" vagy „Webpack" sort az indulásnál. Emellett a .next/build-meta.json tartalmaz egy bundler mezőt, amit a CI-ben grep-pelhetsz: jq -r .bundler .next/build-meta.json.

Mit csináljak, ha egy npm csomag csak Webpacken működik?

Először nézd meg a csomag GitHub issue-it; a legtöbb népszerű csomag már kiadott Turbopack-kompatibilis verziót 2025–2026 folyamán. Ha tényleg nincs megoldás, három opció van: (1) upgrade-elni a csomag újabb verzióját, (2) helyettesíteni Turbopack-kompatibilis alternatívával, (3) addig Webpacken maradni az adott app-pal.

A Turbopack perzisztens cache mappáját be kell rakni a .gitignore-ba?

Igen, a .next/cache/ alapból a Next.js .gitignore sablonban van, és a Turbopack ezt az alkönyvtárat használja. CI-ben pedig a build-cache restore-step-be érdemes felvenni, hogy a runner-ek közt megmaradjon. GitHub Actions-ben az actions/cache@v4 a .next/cache kulcsra elég.

Mei-Lin Wu
A Szerzőről Mei-Lin Wu

Front-end architect at a SaaS. Owns the build system, the design system, and the war stories about both.