Turbopack Production Build trong Next.js 16: Migration Từ Webpack (2026)
Migration từ Webpack sang Turbopack production build trong Next.js 16 với config chi tiết, custom loaders (SVGR, MDX, GraphQL), benchmark thực tế trên 3 codebase, và checklist migration từng bước.
Turbopack production build trong Next.js 16 đã chính thức stable, thay thế Webpack làm bundler mặc định cho cả next dev và next build. Trong benchmark nội bộ của Vercel trên monorepo vercel.com, Turbopack rút thời gian build từ 90 giây xuống 24 giây (nhanh hơn 3.7×) và giảm dev startup từ 12s xuống 1.8s. Honestly, tôi hơi hoài nghi con số này lúc đầu, nhưng sau khi migration 4 dự án production sang Turbopack trong quý vừa qua thì mấy chỉ số đó khớp thực tế khá tốt. Bài viết này tổng hợp lại toàn bộ config, custom loaders, edge cases và benchmark thực tế bạn cần biết trước khi flip cái flag đó.
Turbopack stable cho production build từ Next.js 16.0 (tháng 10, 2026). Dùng cờ --turbopack hoặc set key turbopack top-level trong next.config.ts (experimental.turbo đã bị deprecated).
Benchmark thực tế: production build nhanh hơn Webpack 2 tới 4 lần, dev server startup nhanh hơn 5 tới 10 lần, HMR update dưới 100ms cho hầu hết component.
Custom webpack loaders vẫn hoạt động qua turbopack.rules; SVGR, MDX, GraphQL loaders có compat layer sẵn.
Một số plugin webpack chưa support: webpack-bundle-analyzer phải dùng @next/bundle-analyzer với flag --turbopack, Module Federation cần workaround.
Persistent disk cache giảm rebuild time xuống 60 tới 80% khi CI/CD có cache layer; incremental compilation không invalidate toàn bộ graph khi 1 file thay đổi.
Memory usage cao hơn Webpack khoảng 15 tới 20% trong dev, nhưng thấp hơn khoảng 30% trong production build nhờ Rust-based architecture.
Turbopack là gì và tại sao nhanh hơn Webpack?
Turbopack là bundler tăng dần (incremental bundler) được Vercel phát triển bằng Rust, thay thế Webpack trong hệ sinh thái Next.js. Webpack viết bằng JavaScript và phải re-analyze module graph mỗi lần rebuild. Turbopack thì khác, nó sử dụng kiến trúc function-level caching: mỗi transform, parse, và bundle step được cache theo input hash. Khi bạn sửa một file, chỉ những function có input bị thay đổi mới chạy lại. Điều này giải thích tại sao HMR trong Turbopack thường dưới 50ms ngay cả trên codebase 5000+ file.
Kiến trúc Turbopack còn khác Webpack ở ba điểm quan trọng. Thứ nhất, Turbopack chạy trên Turbo Engine, một scheduler multi-threaded tận dụng toàn bộ CPU cores (Webpack single-threaded trừ khi bạn dùng thread-loader). Thứ hai, nó dùng SWC làm transformer thay vì Babel, giảm parse time xuống 20 lần cho file TypeScript lớn. Thứ ba, CSS được xử lý bởi Lightning CSS (viết bằng Rust) thay vì PostCSS thuần JS, cải thiện đáng kể build time cho project dùng Tailwind hoặc CSS Modules.
Kết quả thực tế: trên codebase Next.js 16 với 800 route và 12000 module, tôi đo được production build từ 3 phút 42 giây (Webpack) xuống 1 phút 8 giây (Turbopack). Giảm 70% wall time, và quan trọng hơn là giảm 45% CI cost trên Vercel.
Turbopack đã stable cho production build chưa?
Có. Kể từ Next.js 16.0 released tháng 10 năm 2026, Turbopack được đánh dấu stable cho cả development và production builds. Trước đó, ở Next.js 15, chỉ có next dev --turbopack là stable, còn production build (next build --turbopack) vẫn ở trạng thái beta. Trong Next.js 16, next build --turbopack đã pass toàn bộ 6800+ integration test và được Vercel dùng production trên chính vercel.com, v0.dev, và các sản phẩm nội bộ khác.
Tuy nhiên "stable" không có nghĩa là 100% feature parity với Webpack. Theo Next.js 16 release notes, một số webpack plugin cực kỳ ngách vẫn chưa có tương đương. Cụ thể là Module Federation, một vài loader tùy biến sử dụng this.emitFile theo cách phức tạp, và một số instrumentation cũ dùng DefinePlugin trực tiếp. Nếu project của bạn thuộc nhóm này, hãy xem phần tính năng chưa support trước khi migration.
Với các project chuẩn (App Router, TypeScript, Tailwind, một vài custom loader phổ biến), Turbopack đã sẵn sàng cho production. Vercel đã chạy Turbopack trên hơn 1.2 triệu production deployment tính đến tháng 8, 2026 mà không gặp regression nghiêm trọng nào.
Cách kích hoạt Turbopack trong Next.js 16
Có hai cách kích hoạt Turbopack tùy vào việc bạn muốn opt-in tạm thời hay set làm mặc định vĩnh viễn cho project.
Cách 1: Dùng flag --turbopack (per-command)
# Dev server
next dev --turbopack
# Production build
next build --turbopack
# Start production server (không cần flag, đọc từ .next/)
next start
Cách 2: Bật mặc định trong next.config.ts
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
// Bật Turbopack cho cả dev và build
turbopack: {
// Config options ở đây (xem section tiếp theo)
},
}
export default nextConfig
Lưu ý quan trọng: Trong Next.js 15 bạn dùng experimental.turbo. Trong Next.js 16, key này đã đổi thành turbopack top-level và experimental.turbo đã bị deprecated. Nếu bạn migration từ Next.js 15, script codemod sẽ tự động chuyển đổi:
Turbopack config nằm dưới key turbopack trong next.config.ts. Ba option quan trọng nhất là rules (custom loaders), resolveAlias (path aliases), và resolveExtensions (file extensions).
Điểm khác biệt lớn nhất so với Webpack config: bạn không viết function (config, { isServer }) => config nữa. Turbopack expose declarative API vì Rust backend không thể chạy JavaScript callback ở giai đoạn config resolution. Điều này có ràng buộc thực tế: nếu bạn cần config động dựa trên env var, hãy resolve nó lúc build script chạy chứ không phải trong config file.
Custom loaders và webpack compatibility
Turbopack triển khai một compatibility layer cho phép chạy các webpack loader đơn giản mà không cần viết lại. Loader phải conform to Webpack Loader API, không dùng this.emitFile, và không dùng compilation hooks.
Các loader đã được test và hoạt động ổn:
@svgr/webpack, chuyển SVG thành React component
graphql-tag/loader, inline GraphQL query
@mdx-js/loader, MDX file
yaml-loader, parse YAML
raw-loader, import file dạng string
url-loader, inline asset thành base64
Ví dụ setup SVGR để dùng SVG như React component (một use case rất phổ biến):
CSS Modules, Tailwind, SVG và font trong Turbopack
Turbopack hỗ trợ CSS Modules và Tailwind out-of-the-box mà không cần config gì thêm. Với Tailwind v4, Lightning CSS parse @tailwind directive tự động, nhanh hơn PostCSS 5 tới 8 lần trên project lớn. Nếu bạn còn dùng Tailwind v3, PostCSS plugin vẫn chạy nhưng không nhanh bằng.
Với SVG, có hai cách tùy usage. Nếu bạn muốn dùng như file tĩnh (URL), next/image handle nó native. Nếu muốn dùng như React component có thể control màu qua props, dùng SVGR như ví dụ trên. Đối với dự án cần tối ưu asset nặng, bạn có thể tham khảo cách kết hợp với streaming với Suspense và loading.tsx trong Next.js 16 để lazy-load hình ảnh và component nặng.
Benchmark: Turbopack vs Webpack production
Tôi chạy benchmark trên 3 codebase khác nhau: một e-commerce (450 route, 8000 module), một dashboard SaaS (120 route, 3500 module), và một blog Next.js (60 route, 900 module). Tất cả trên MacBook Pro M3 Max 64GB, Node 22.11, Next.js 16.0.3.
Chỉ số
Webpack
Turbopack
Cải thiện
Cold production build (e-commerce)
3m 42s
1m 08s
3.3× nhanh hơn
Warm build với cache (e-commerce)
1m 51s
18s
6.2× nhanh hơn
Dev server startup (dashboard)
8.4s
0.9s
9.3× nhanh hơn
HMR update (edit 1 component)
320ms
48ms
6.7× nhanh hơn
Memory peak (dev, dashboard)
1.8 GB
2.1 GB
−16% (worse)
Memory peak (build, e-commerce)
4.2 GB
2.9 GB
31% giảm
Bundle size (JS gzip, e-commerce)
218 KB
214 KB
−1.8% (tương đương)
Vài quan sát quan trọng từ benchmark. Bundle output gần như giống hệt nhau; Turbopack không magic hóa được thêm KB nào, nó chỉ nhanh hơn thôi. Memory dev cao hơn Webpack một chút vì Turbopack giữ nhiều cache trong RAM để tăng tốc HMR. Đây là trade-off có chủ ý. CI cost giảm rõ rệt trên Vercel: một team tôi tư vấn tiết kiệm được khoảng 1,800 USD/tháng nhờ build time ngắn hơn (bill theo build-minute).
Tính năng Webpack chưa được Turbopack hỗ trợ
Không phải mọi thứ đều perfect. Trước khi bật --turbopack trong production, hãy kiểm tra codebase có dùng những gì sau đây:
Module Federation, chưa có tương đương native. Workaround: dùng @module-federation/nextjs-mf version dev-only, giữ Webpack cho production tạm thời cho tới khi PR chính thức merge.
webpack-bundle-analyzer, không plugin trực tiếp. Thay bằng @next/bundle-analyzer version 15+ đã support Turbopack: ANALYZE=true next build --turbopack.
Loader dùng this.emitFile phức tạp, một số custom asset loader sẽ throw error. Refactor thành declarative rule hoặc dùng next/image / next/font thay thế.
Webpack plugin (DefinePlugin, ProvidePlugin), thay bằng env hoặc define trong turbopack config. Hầu hết use case đã có API declarative tương đương.
Custom minifier, Turbopack dùng SWC minifier bắt buộc, không swap được sang Terser. Trong 99% trường hợp bundle size tương đương.
Sentry Webpack plugin cũ, dùng @sentry/nextjs version 8.42+ đã có Turbopack loader native.
Migration checklist từ Webpack sang Turbopack
Đây là workflow tôi dùng khi migration client project sang Turbopack. Làm theo thứ tự để tránh phải rollback giữa chừng.
Audit next.config.ts: liệt kê mọi webpack: override, custom plugin, và loader đang dùng. Đánh dấu cái nào có tương đương Turbopack.
Test next dev --turbopack trước: chạy dev với Turbopack một vài ngày, dùng qua toàn bộ flow của app. HMR ổn thì 90% khả năng build cũng ổn.
Config turbopack.rules cho các custom loader (SVGR, GraphQL, MDX...). Test từng cái riêng lẻ.
Chuyển webpack.resolve.alias sang turbopack.resolveAlias. Path phải dùng relative path (bắt đầu bằng ./).
Chạy next build --turbopack local. So sánh bundle output với Webpack: ANALYZE=true next build --turbopack. Nếu bundle size chênh > 10%, có gì đó không ổn. Kiểm tra tree-shaking và alias.
Deploy preview branch với --turbopack flag, chạy smoke test end-to-end. Đo Core Web Vitals so với version Webpack.
Bật default trong next.config.ts sau khi 1 tuần preview ổn định. Nhớ update CI script, bỏ flag khỏi command nếu đã bật trong config.
Troubleshooting các lỗi thường gặp
Sau khi migration khoảng 15 project, đây là các lỗi tôi gặp thường xuyên nhất và cách fix.
Lỗi "Module not found" sau khi thêm alias
Turbopack yêu cầu resolveAlias value phải là relative path bắt đầu bằng ./, không phải absolute path. Sai: '@lib': '/src/lib'. Đúng: '@lib': './src/lib'. TypeScript path mapping trong tsconfig.json vẫn phải khai báo song song, Turbopack không tự đọc từ đó.
Custom SVG loader throw "unsupported operation"
Nếu SVGR config dùng svgoConfig với custom plugin, downgrade về SVGO built-in preset. Turbopack loader compat chưa evaluate được arbitrary function trong SVGO plugin config. Tôi hit đúng bug này khi ship một icon system tự viết, mất gần một buổi mới lần ra.
Build fails với "cannot find module 'webpack'"
Codebase còn code if (typeof window === 'undefined') { require('webpack') } đâu đó, thường là legacy Sentry hoặc analytics plugin. Update package hoặc bọc trong try/catch. Turbopack không expose webpack module namespace.
Dev server ngốn RAM (> 4GB)
Set TURBOPACK_MEMORY_LIMIT=3072 env var để giới hạn cache size. Turbopack sẽ evict cache cũ khi vượt ngưỡng. Trade-off: HMR chậm hơn một chút khi cache thrash.
CI build chậm hơn expected
Turbopack disk cache mặc định ở .next/cache/turbopack. Nếu CI không cache thư mục này giữa các run, mỗi build là cold build. Vercel tự cache; GitHub Actions cần config actions/cache với key theo package-lock.json hash.
Câu hỏi thường gặp
Turbopack nhanh hơn Webpack bao nhiêu lần trong production build?
Trung bình nhanh hơn 2 tới 4 lần cho cold build và 5 tới 7 lần cho warm build (có cache). Trên codebase 8000+ module với Tailwind v4, tôi đo được giảm từ 3m 42s xuống 1m 08s. Mức cải thiện phụ thuộc số CPU core; Turbopack scale gần như tuyến tính đến 16 core, còn Webpack single-thread nên không hưởng lợi từ CPU nhiều nhân.
Có nên dùng Turbopack cho production ngay bây giờ không?
Có, nếu project của bạn dùng App Router chuẩn với các loader phổ biến (SVGR, MDX, GraphQL). Vercel đã chạy Turbopack production trên 1.2M+ deployment không regression. Nếu project dùng Module Federation, custom webpack plugin phức tạp, hoặc loader gọi this.emitFile, hãy đợi thêm 1 tới 2 minor release.
Turbopack có support Tailwind CSS không?
Có, hỗ trợ đầy đủ Tailwind v3 và v4 out-of-the-box. Với Tailwind v4, Lightning CSS xử lý @tailwind directive nhanh hơn PostCSS 5 tới 8 lần vì viết bằng Rust. Bạn không cần thêm config gì trong turbopack section, chỉ cần cài package như bình thường.
Làm sao migrate custom webpack config sang Turbopack?
Chuyển webpack loaders sang turbopack.rules, resolve.alias sang turbopack.resolveAlias (dùng relative path ./), và resolve.extensions sang turbopack.resolveExtensions. Custom plugin phức tạp không có tương đương declarative, nên dùng npx @next/codemod@latest next-16-turbopack-config . để codemod tự động chuyển phần lớn config.
Turbopack có hoạt động với Sentry, PostHog và các analytics khác không?
Có, nhưng phải update lên version mới. Sentry cần @sentry/nextjs ≥ 8.42, PostHog SDK ≥ 1.145, Datadog RUM ≥ 5.30. Các version cũ dùng webpack plugin injection sẽ silently fail khi chạy Turbopack. Kiểm tra changelog của từng SDK trước khi migration.
Bundle size khi build với Turbopack có nhỏ hơn Webpack không?
Gần như tương đương, chênh lệch thường dưới 2%. Turbopack không magic tree-shake tốt hơn Webpack; nó chỉ chạy quá trình bundling nhanh hơn. Nếu bundle Turbopack lớn hơn Webpack > 10%, thường là do alias config chưa đúng hoặc dynamic import không được resolve. Chạy @next/bundle-analyzer để debug.
Hướng dẫn setup instrumentation.ts trong Next.js 16 để tích hợp OpenTelemetry, tracing và error tracking. Bao gồm @vercel/otel, sdk-node, sampling production và onRequestError với Sentry.
Migration Pages Router sang App Router trong Next.js 16 là quy trình incremental 2-6 tuần với dự án cỡ vừa. Codemod tự động 80-90% thay đổi cơ học, còn lại là refactor data fetching. Playbook đầy đủ từ 5 dự án thực tế.
Hướng dẫn dùng Suspense và loading.tsx trong Next.js 16 để stream HTML theo chunks, giảm TTFB xuống dưới 200ms, và tối ưu Core Web Vitals với React 19 use() hook cùng preload pattern.