npx skills add ...
npx skills add vercel/vercel-plugin --skill turbopack
npx skills add vercel/vercel-plugin --skill turbopack
Turbopack expert guidance. Use when configuring the Next.js bundler, optimizing HMR, debugging build issues, or understanding the Turbopack vs Webpack differences.
The same skill content is published under more than one repo. The install counts are split across them; any of these commands works.
You are an expert in Turbopack — the Rust-powered JavaScript/TypeScript bundler built by Vercel. It is the default bundler in Next.js 16.
In Next.js 16, Turbopack config is top-level (moved from experimental.turbopack):
Turbopack handles CSS natively without additional configuration.
Import global CSS in your root layout:
CSS Modules work out of the box with .module.css files:
Turbopack reads your postcss.config.js automatically. Tailwind CSS v4 works with zero config:
Install sass and import .scss files directly — Turbopack compiles them natively:
@import in global CSS: Use standard CSS @import — Turbopack resolves them, but circular imports cause build failures.styled-components and emotion work but require their SWC plugins configured under compiler in next.config.Turbopack performs tree shaking at the module level in production builds. Key behaviors:
export on each function/constant rather than barrel export *package.json to enable aggressive tree shaking:index.ts) when the package declares "sideEffects": falseimport() expressions create async chunk boundaries — Turbopack splits these into separate chunks automaticallyBuilt-in analyzer (Next.js 16.1+, experimental): Works natively with Turbopack. Offers route-specific filtering, import tracing, and RSC boundary analysis:
Legacy @next/bundle-analyzer: Still works as a fallback:
Turbopack does not support webpack loaders directly. Here is how to migrate common patterns:
| Webpack Loader | Turbopack Equivalent |
|---|---|
css-loader + style-loader | Built-in CSS support — remove loaders |
sass-loader | Built-in — install sass package |
postcss-loader | Built-in — reads postcss.config.js |
file-loader / url-loader | Built-in static asset handling |
svgr / @svgr/webpack | Use @svgr/webpack via turbopack.rules |
raw-loader | Use import x from './file?raw' |
graphql-tag/loader | Use a build-time codegen step instead |
worker-loader | Use native new Worker(new URL(...)) syntax |
For loaders that have no built-in equivalent, use turbopack.rules:
If a webpack loader has no Turbopack equivalent and no workaround, fall back to webpack:
File an issue at github.com/vercel/next.js — the Turbopack team tracks loader parity requests.
webpack() function from next.config — it's ignored by Turbopack and may mask the real configturbopack.rules: Ensure custom rules reference valid loaders that are installedfs, path, etc. cannot be imported in client or edge bundlesturbopack.resolveAlias covers any custom resolution that was previously in webpack config"use client" directives — each client component boundary creates a new chunkserver-only package to enforce server/client boundaries at import time:Run both bundlers and compare:
Compare .next/ output sizes and page-level chunks.
Enable verbose HMR timing in development:
This writes a trace.json to the project root — open it in chrome://tracing or Perfetto to see module-level timing.
Profile production builds:
Look for:
Turbopack's Rust core manages its own memory. If builds OOM:
NODE_OPTIONS='--max-old-space-size=8192' next buildturbo build --concurrency=2| Feature | Turbopack | Webpack |
|---|---|---|
| Language | Rust | JavaScript |
| HMR speed | Constant (O(1)) | Degrades with app size |
| RSC support | Native | Plugin-based |
| Cold start | Fast | Slower |
| Ecosystem | Growing | Massive (loaders, plugins) |
| Status in Next.js 16 | Default | Still supported |
| Tree shaking | Module-level | Module-level |
| CSS handling | Built-in | Requires loaders |
| Production builds | Supported | Supported |
ModuleFederationPlugin)externals functions)To use webpack instead:
experimental.turbopack to top-level turbopack in next.config.turbopack.resolveAlias instead of webpack.resolve.alias.server-only package.// app/layout.tsx
import './globals.css'// components/Button.tsx
import styles from './Button.module.css'
export function Button({ children }) {
return <button className={styles.primary}>{children}</button>
}// postcss.config.js
module.exports = {
plugins: {
'@tailwindcss/postcss': {},
autoprefixer: {},
},
}npm install sassimport styles from './Component.module.scss'{
"name": "my-ui-lib",
"sideEffects": false
}// next.config.ts
const nextConfig: NextConfig = {
experimental: {
bundleAnalyzer: true,
},
}ANALYZE=true next build// next.config.ts
import withBundleAnalyzer from '@next/bundle-analyzer'
const nextConfig = withBundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
})({
// your config
})// next.config.ts
const nextConfig: NextConfig = {
turbopack: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
}const nextConfig: NextConfig = {
bundler: 'webpack',
}npm install server-only// lib/db.ts
import 'server-only' // Build fails if imported in a client component# Turbopack build (default in Next.js 16)
next build
# Webpack build
BUNDLER=webpack next buildNEXT_TURBOPACK_TRACING=1 next devNEXT_TURBOPACK_TRACING=1 next build// next.config.ts
const nextConfig: NextConfig = {
bundler: 'webpack', // Opt out of Turbopack
}