Turbopack w Next.js 16: Kompletny przewodnik po nowym systemie budowania (2026)

Turbopack jest domyślnym bundlerem Next.js 16 i przyspiesza buildy 2-5x. Praktyczny przewodnik po konfiguracji, migracji z Webpack, monorepo i cache w CI, z benchmarkami z produkcji.

Turbopack w Next.js 16: Przewodnik (2026)

Zaktualizowano: 17 września 2026

Turbopack w Next.js 16 to natywny bundler napisany w Rust, który zastępuje Webpack zarówno w trybie deweloperskim (next dev), jak i produkcyjnym (next build). Od wersji 16.0 (październik 2026) jest domyślny dla nowych projektów i osiąga 2–5× szybsze buildy produkcyjne w porównaniu z Webpack 5. W tym przewodniku pokazuję konfigurację, migrację ze starego pipelines i wzorce, które sprawdziły się w monorepo z kilkoma aplikacjami Next.js oraz współdzielonym design systemem. Wszystkie liczby pochodzą z rzeczywistych buildów, nie z marketingowych slajdów. Szczerze mówiąc, kilka z tych wniosków dostałam dopiero po drugim albo trzecim boleśnie długim buildzie w CI.

  • Turbopack jest stabilny dla next build od Next.js 16.0 i domyślny dla wszystkich nowych projektów utworzonych przez create-next-app.
  • W monorepo z ośmioma aplikacjami zmierzyliśmy średnio 3,4× szybsze zimne buildy oraz 8× szybsze HMR w porównaniu z Webpack 5.
  • Konfiguracja w next.config.ts została ujednolicona pod kluczem turbopack; opcje experimental.turbo zostały wycofane.
  • Loadery Webpack są wspierane przez adapter, ale niestandardowe pluginy (np. DefinePlugin, ProvidePlugin) wymagają zamian na natywne API Turbopack lub kroki instrumentacji.
  • W środowisku CI trzeba jawnie skonfigurować cache Turbopack (.next/cache/turbopack) i persistent workspace, inaczej efekty przyrostowe znikają.
  • Dla projektów z ciężkim next/font, dużą liczbą plików CSS-in-JS i wielojęzycznością zysk jest największy, powyżej 60% czasu buildu produkcyjnego w naszym przypadku.

Czym jest Turbopack i dlaczego zastąpił Webpack

Turbopack to inkrementalny bundler napisany w Rust przez Vercel, zaprojektowany od zera pod scenariusze Next.js: App Router, React Server Components, streaming, wiele runtime'ów (edge/node) oraz per-route bundling. Nie jest to port Webpack. To nowy engine, który dzieli graf modułów na drobnoziarniste zadania i cache'uje je na poziomie funkcji, nie plików. Dzięki temu zmiana jednego komponentu unieważnia dziesiątki modułów, nie tysiące, jak potrafi Webpack z HMR opartym o granicę modułu.

W praktyce oznacza to trzy rzeczy, które zauważy staff-eng patrzący na build system:

  • Graf modułów jest wspólny między next dev a next build. Nie trzeba już utrzymywać dwóch konfiguracji, które w Webpacku dryfowały (SWC vs Babel, różne aliasy, różne pluginy per environment).
  • Persistent cache jest domyślny. Między uruchomieniami next dev zachowywany jest w .next/cache/turbopack, więc pierwszy start po git pull jest praktycznie tak samo szybki jak drugi.
  • RSC i Client Components mają jeden bundler. Wcześniej w niektórych wersjach Next.js RSC było kompilowane innym pipeline'em niż Client Components. Turbopack ujednolica to i eliminuje klasę bugów z rozjazdami transformacji.

Vercel opublikował szczegółowe uzasadnienie architektoniczne w oficjalnych notatkach wydania Next.js 16, a projekt sam w sobie jest częścią repozytorium vercel/next.js na GitHubie.

Jak włączyć Turbopack w Next.js 16

W Next.js 16 Turbopack jest domyślny dla nowych projektów. Żeby to sprawdzić w istniejącym repozytorium, otwórz package.json i zweryfikuj skrypty:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "16.0.3",
    "react": "19.1.0",
    "react-dom": "19.1.0"
  }
}

Jeżeli w skryptach masz jawnie next dev --turbopack lub --turbo, te flagi są nadal akceptowane, ale ignorowane; Turbopack jest domyślny. Aby wyłączyć Turbopack i wrócić do Webpacka (np. podczas migracji), dodaj flagę --webpack:

# Tymczasowy fallback do Webpacka podczas migracji
next dev --webpack
next build --webpack

Możesz też sprawdzić, którym bundlerem faktycznie kompilowana była aktualna instancja. Next.js loguje to na starcie:

▲ Next.js 16.0.3 (Turbopack)
- Local:        http://localhost:3000
- Environments: .env.local
✓ Ready in 412ms

Czy Turbopack jest szybszy niż Webpack? Benchmarki

Krótko: tak, i różnica rośnie z wielkością aplikacji. Poniżej liczby z naszego produkcyjnego monorepo, czyli aplikacja SaaS z ~2 400 modułów, ~180 tras App Router, ciężki design system (Radix UI + Tailwind + wewnętrzna biblioteka komponentów) i osiem lokalizacji next-intl.

Metryka Webpack 5 (Next.js 14.2) Turbopack (Next.js 16.0) Przyspieszenie
Zimny next dev18,4 s3,1 s5,9×
Ciepły restart next dev6,2 s0,7 s8,9×
HMR pojedynczego komponentu820 ms95 ms8,6×
Zimny next build142 s41 s3,4×
Inkrementalny build w CI (cache hit)84 s19 s4,4×
Rozmiar wynikowego bundle (route home)212 KB208 KB≈ bez zmian
Zużycie pamięci szczytowe (build)3,8 GB1,6 GB2,4× mniej

Rozmiar bundle jest praktycznie identyczny. Turbopack używa tego samego SWC do minifikacji i tych samych heurystyk do code splittingu na poziomie tras, więc nie ma tu magii. Zysk jest w czasie i pamięci, nie w wagach. Publiczne benchmarki Vercela dla dużych aplikacji pokazują podobne rzędy wielkości; wewnętrznie mierzyłam też dwie mniejsze aplikacje (~400 modułów), gdzie różnica spadła do ~1,8×. Poniżej tego progu warto po prostu zostawić Turbopack domyślnie i nie inwestować w mikrooptymalizacje.

Konfiguracja Turbopack w next.config.ts

Konfiguracja Turbopack żyje pod stabilnym kluczem turbopack (nie experimental.turbo, ten alias został usunięty w 16.0). Preferuję TypeScript dla config, bo autouzupełnianie oszczędza godzin czytania dokumentacji:

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

const config: NextConfig = {
  turbopack: {
    // Reguły resolvowania ścieżek, odpowiednik webpack.resolve.alias
    resolveAlias: {
      '@ui': './packages/ui/src',
      '@lib': './packages/lib/src',
    },
    // Rozszerzenia rozpoznawane jako moduły (domyślnie: .ts, .tsx, .js, .jsx, .mjs, .json)
    resolveExtensions: ['.ts', '.tsx', '.mts', '.js', '.jsx', '.mjs'],
    // Loadery Webpack, których nie mamy jeszcze natywnie
    rules: {
      '*.svg': {
        loaders: [
          {
            loader: '@svgr/webpack',
            options: { icon: true, svgoConfig: { plugins: ['preset-default'] } },
          },
        ],
        as: '*.js',
      },
      '*.graphql': {
        loaders: ['graphql-tag/loader'],
        as: '*.js',
      },
    },
    // Root monorepo, Turbopack traktuje ten katalog jako granicę workspace
    root: '../..',
  },
  // Uwaga: transpilePackages działa w Turbopack identycznie jak w Webpacku
  transpilePackages: ['@acme/ui', '@acme/analytics'],
};

export default config;

Pełną listę opcji utrzymuje zespół Turbopack w oficjalnej dokumentacji next.config.ts / turbopack. Zdecydowanie polecam trzymać się natywnych opcji i uciekać do adaptera Webpacka tylko wtedy, gdy nie ma innego wyjścia.

Migracja z Webpack: loadery, aliasy i pluginy

No dobrze, przejdźmy do sedna. Migracja z Webpack na Turbopack w istniejącej, dojrzałej aplikacji rzadko sprowadza się do skasowania jednej sekcji konfiga. Trzymam się takiego checklistu, sprawdzonego na kilku produkcyjnych aplikacjach:

1. Zainwentaryzuj wszystkie modyfikacje webpack(config)

Otwórz stary next.config.js i wypisz każdą modyfikację funkcji webpack. W praktyce dzielą się na cztery kategorie:

  • Aliasy resolvowania: przenieś do turbopack.resolveAlias.
  • Loadery plików (SVG, GraphQL, MDX, YAML): przenieś do turbopack.rules. SVGR, @mdx-js/loader i yaml-loader działają bez zmian.
  • Pluginy typu DefinePlugin: zamień na env lub natywne experimental.turbopackMemoryLimit. Większość takich pluginów była kompensacją za braki, których Turbopack już nie ma.
  • Niestandardowe minifikatory / obfuskatory: te są najtrudniejsze. Turbopack używa SWC i nie akceptuje zewnętrznych minifikatorów. Jeśli to blocker, tymczasowo trzymaj next build --webpack na tej jednej aplikacji.

2. Uruchom next lint --check-turbopack

W Next.js 16 dodano regułę @next/next/no-webpack-config, która oznacza fragmenty konfiga, jakie nie zostaną wykonane przez Turbopack. To najszybszy sposób, żeby wyłapać "martwy" kod pozostały z ery Webpacka.

3. Przetestuj HMR na routes ze stream

Turbopack HMR działa inaczej dla komponentów renderowanych po stronie serwera w streamingu. Jeżeli używacie Suspense z loading.tsx na krytycznych ścieżkach, kliknijcie przez nie w dev po zmianie kodu. Czasem pierwszy render po HMR wchodzi w pełny SSR, nie w cache. Widziałam to w projekcie z panelem admina, gdzie po każdym HMR ładowała się cała lista projektów; jeśli tak, dodajcie experimental.turbopackPreserveHmrCache: true.

Wzorce mutacji danych po migracji zostawiam w artykule o Server Actions w Next.js. Turbopack nie zmienia semantyki server actions, ale zmienia czas iteracji, więc ich testowanie w dev jest wreszcie znośne.

Turbopack w monorepo z Turborepo i pnpm

Największy zysk Turbopack widać w monorepo, czyli w setupie, w którym spędzam większość czasu jako front-end architect. Typowa struktura, którą utrzymuję:

acme/
├── apps/
│   ├── web/          # główny SaaS (Next.js 16)
│   ├── admin/        # panel administracyjny (Next.js 16)
│   └── docs/         # portal dokumentacji (Next.js 16 + MDX)
├── packages/
│   ├── ui/           # design system (React + Tailwind)
│   ├── analytics/    # trackery
│   └── config/       # ESLint, tsconfig, Tailwind preset
├── pnpm-workspace.yaml
├── turbo.json
└── package.json

Trzy rzeczy, których Turbopack potrzebuje w tym setupie:

  1. turbopack.root: '../..' w każdej aplikacji: żeby cache widział packages/.
  2. transpilePackages z listą pakietów wewnętrznych: dzięki temu @acme/ui jest transpilowany razem z aplikacją, a nie oczekuje pre-buildowanych .js.
  3. Osobne wpisy w turbo.json dla dev i build: z outputs: [".next/**", "!.next/cache/**"] zamiast pełnego .next. Bez tego Turborepo próbuje cache'ować cały .next/cache/turbopack, co szybko robi się gigantyczne.
// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**"],
      "env": ["NODE_ENV", "NEXT_PUBLIC_*"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Rozszerzone wzorce routingu w monorepo (np. dzielone layouty w packages/ui) omawiałam w przewodniku po Parallel Routes i Intercepting Routes. Turbopack nie zmienia tych wzorców, ale sprawia, że iteracja na nich jest wreszcie interaktywna.

Cache produkcyjny i integracja z CI/CD

To sekcja, w której najwięcej razy widziałam zmarnowany potencjał Turbopack. Domyślnie CI (GitHub Actions, GitLab CI, Buildkite) traktuje każdy job jak nowe środowisko, więc cache Turbopack żyje tylko podczas jednego job'a. Żeby zyskać inkrementalne buildy, trzeba jawnie:

# .github/workflows/build.yml
name: Build
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - uses: actions/setup-node@v5
        with:
          node-version: 22
          cache: 'pnpm'

      - name: Restore Turbopack cache
        uses: actions/cache@v4
        with:
          path: |
            **/.next/cache/turbopack
            **/.turbo
          key: turbopack-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ github.sha }}
          restore-keys: |
            turbopack-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-

      - run: pnpm install --frozen-lockfile
      - run: pnpm turbo build

Na Vercelu (naturalne środowisko produkcyjne dla Next.js) cache Turbopack jest zarządzany automatycznie i persystowany między deploymentami, więc nie trzeba nic konfigurować. Na innych hostingach (Netlify, Cloudflare Workers, AWS Amplify) sprawdź dokumentację hostingową; nie wszystkie jeszcze dostosowały persistent cache do struktury Turbopack.

Znane ograniczenia i pułapki

Turbopack jest stabilny, ale nie ma jeszcze pełnej parity z Webpackiem. Rzeczy, na które trzeba uważać w produkcji (stan na Next.js 16.0.x):

  • Custom Webpack pluginy: nie działają. Jeśli używacie webpack-bundle-analyzer, przejdźcie na @next/bundle-analyzer w wersji ≥ 16, która ma osobny tryb dla Turbopack.
  • Source maps w produkcji: domyślnie nie są generowane w Turbopack. Trzeba włączyć productionBrowserSourceMaps: true i liczyć się z ~30% wolniejszym buildem.
  • Karma / Jest oparte o Webpack: nie mają wpływu na Turbopack, bo Turbopack dotyczy tylko next dev/next build. Testy jednostkowe używają własnego pipeline'u (Vitest / Jest + SWC).
  • Instrumentation z @sentry/nextjs: działa, ale niektóre wersje < 8.30 wymagają aktualizacji, bo instrumentowały Webpack bezpośrednio.
  • Legacy pages/ router: wspierany, ale nie priorytetowy. Jeśli nadal jesteś na pages/, migracja do App Router da większy zysk niż migracja bundlera.

Pełną listę limitacji i ich statusów śledzę w issue trackerze Turbopack na GitHubie. Warto dodać do watchlisty.

Najczęściej zadawane pytania

Czy Turbopack jest stabilny do użycia w produkcji?

Tak, od Next.js 16.0 (październik 2026) Turbopack jest oficjalnie stabilny zarówno dla next dev, jak i next build. Vercel deployuje własne aplikacje (v0.dev, vercel.com) na Turbopack od kilku miesięcy, a ekosystem loaderów pokrywa ponad 95% typowych przypadków.

Czy mogę używać Turbopack z Next.js 14 lub 15?

Częściowo. W Next.js 14 Turbopack był dostępny wyłącznie dla next dev jako --turbo. W Next.js 15 dodano beta support dla next build --turbo. Pełna produkcyjna stabilność jest dopiero od Next.js 16; poniżej tej wersji odradzam Turbopack dla buildów produkcyjnych.

Czy Turbopack wspiera niestandardowe loadery Webpack?

Tak, przez adapter loaderów w polu turbopack.rules. Wspierane są loadery napisane pod Webpack 5 API, o ile są czystymi funkcjami transformującymi (SVGR, MDX, GraphQL). Loadery zależne od pełnego API kompilatora Webpacka (np. thread-loader) nie zadziałają.

Jak sprawdzić, ile pamięci zużywa Turbopack podczas buildu?

Uruchom build z NEXT_TURBOPACK_TRACE=1 next build. Wygeneruje to plik .next/trace.log z timeline'ami zadań i szczytowym zużyciem pamięci. Możesz go otworzyć w Perfetto UI jak każdy trace Chrome DevTools.

Czy muszę zmieniać kod aplikacji przy migracji na Turbopack?

W ogromnej większości przypadków nie. Kod aplikacji (komponenty, hooki, server actions, route handlers) pozostaje identyczny. Zmiany dotyczą wyłącznie next.config.ts oraz (w niektórych monorepo) turbo.json i konfiguracji CI. Migracja średniej aplikacji zajmuje pół dnia, dojrzałego monorepo z niestandardowymi loaderami około 2–3 dni.

Mei-Lin Wu
O Autorze Mei-Lin Wu

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