JavaScript bundling has lengthy been the efficiency ceiling for big Subsequent.js initiatives. Sluggish sizzling module substitute, painful chilly begins exceeding 10 seconds on sizeable codebases, and costly CI builds that eat by compute minutes have outlined the developer expertise for years. Turbopack’s stabilization in Subsequent.js 15 delivers the biggest measured velocity enchancment the framework has shipped because the App Router: Vercel’s benchmarks report as much as 76% quicker chilly begins in comparison with Webpack.
Turbopack is now not hidden behind an experimental flag for growth. As of Subsequent.js 15, it ships as a steady, default-ready bundler for subsequent dev, with energetic progress towards manufacturing construct assist. This tutorial covers the complete path: enabling Turbopack, configuring it for real-world stacks, benchmarking precise efficiency good points, troubleshooting frequent breakages, and assessing manufacturing readiness.
Desk of Contents
What Is Turbopack and Why It Issues
Turbopack vs. Webpack: Structure at a Look
Turbopack is a Rust-based incremental computation engine designed as Webpack’s successor throughout the Subsequent.js ecosystem. The place Webpack processes and bundles modules by a JavaScript-based pipeline, Turbopack makes use of Rust’s efficiency traits alongside two key architectural selections: function-level caching and lazy bundling. Operate-level caching (the place every transformation step is individually memoized by its inputs) means Turbopack remembers the results of each computation and solely recomputes what has modified. Lazy bundling means it solely processes modules really requested by the browser, slightly than eagerly constructing a whole dependency graph upfront.
That is distinct from instruments like Vite, which makes use of esbuild for dependency pre-bundling and native ES modules for dev serving. Turbopack takes a special method, working as a unified incremental engine slightly than composing a number of instruments.
Operate-level caching (the place every transformation step is individually memoized by its inputs) means Turbopack remembers the results of each computation and solely recomputes what has modified.
Stability Milestones in Subsequent.js 15
Turbopack’s journey started as an experimental flag in Subsequent.js 13, matured by Subsequent.js 14 with expanded check protection, and reached steady standing for subsequent dev in Subsequent.js 15. Turbopack is marked steady as a result of it handed the Subsequent.js integration check suite on the time of the Subsequent.js 15 launch. Test the Subsequent.js 15 launch notes for the precise pass-rate threshold and methodology. The subsequent construct --turbo path stays in energetic growth. To test its present standing, go to the Turbopack API reference or run npx subsequent construct --turbo and examine the warning banner within the output. If nonetheless experimental, Subsequent.js prints a warning; if steady, no warning seems.
Enabling Turbopack in Your Subsequent.js 15 Undertaking
Recent Undertaking Setup
Ranging from scratch is the best path. Creating a brand new undertaking and launching the dev server with Turbopack requires simply two instructions:
npx create-next-app@newest my-turbo-app
cd my-turbo-app
npx subsequent dev --turbo
That is the zero-config joyful path. Subsequent.js 15’s scaffolding produces a undertaking construction totally appropriate with Turbopack out of the field, with no extra configuration information or dependencies required.
Migrating an Current Undertaking
For present initiatives, the migration entails updating the dev script in package deal.json and reviewing subsequent.config.js for any Webpack-specific configuration that wants translation:
{
"scripts": {
"dev": "subsequent dev --turbo",
"construct": "subsequent construct",
"begin": "subsequent begin",
"lint": "subsequent lint"
}
}
If the undertaking makes use of a subsequent.config.js with customized Webpack configuration, these customizations will have to be migrated to Turbopack’s configuration floor (coated within the configuration part beneath). Earlier than working, confirm the undertaking meets the minimal necessities: Subsequent.js 15 or later and Node.js 18.18.0 or later. Run npm ls subsequent or yarn why subsequent to substantiate peer dependency alignment — search for subsequent@15.x.x within the output to substantiate the put in model — significantly if the undertaking makes use of packages that pin particular Subsequent.js variations.
Verifying Turbopack Is Lively
After launching the dev server, the terminal output explicitly confirms which bundler is working. Search for this within the startup log:
â–² Subsequent.js 15.x.x
- Native: http://localhost:3000
- Turbopack prepared
The presence of “Turbopack prepared” (versus the usual Webpack compilation messages) confirms the change took impact. If the output reveals “compiled efficiently” with Webpack-style chunk data as an alternative, Turbopack will not be energetic and the --turbo flag will not be reaching the dev command accurately. Double-check the package deal.json script or cross the flag straight through the command line.
Benchmarking the Pace Wins
Chilly Begin Time
Measuring chilly begin time requires a managed, reproducible method. The next shell script compares startup instances between Webpack and Turbopack by clearing caches and timing the preliminary server prepared occasion:
#!/bin/bash
PORT=3099
WAIT_TIMEOUT=60000
clear_caches() {
[ -d ".next" ] && rm -rf .subsequent
[ -d "node_modules/.cache" ] && rm -rf node_modules/.cache
}
run_timed() {
native label="$1"
native turbo_flag="$2"
clear_caches
echo "--- ${label} ---"
npx subsequent dev --port "$PORT" ${turbo_flag} &
DEV_PID=$!
START=$(date +%spercentN)
if ! npx wait-on --timeout "$WAIT_TIMEOUT" "http://localhost:${PORT}"; then
echo "ERROR: dev server didn't begin inside timeout." >&2
kill "$DEV_PID" 2>/dev/null
return 1
fi
END=$(date +%spercentN)
echo "${label}: $(( (END - START) / 1000000 ))ms"
kill "$DEV_PID" 2>/dev/null
wait "$DEV_PID" 2>/dev/null
}
run_timed "Webpack Chilly Begin" ""
run_timed "Turbopack Chilly Begin" "--turbo"
Vercel’s printed benchmarks report as much as 76% quicker chilly begins with Turbopack in comparison with Webpack. This determine comes from Vercel’s Turbopack benchmarks web page (see turbo.construct/pack/docs/benchmarks for methodology particulars, together with undertaking measurement and {hardware} specs). Actual-world outcomes will differ relying on machine {hardware}, undertaking measurement, dependency rely, and working system. Run the script above towards your individual undertaking and examine to your Webpack baseline slightly than treating 76% as a assured determine.
Scorching Module Substitute (HMR)
Turbopack’s HMR velocity benefit stems straight from its incremental computation mannequin. When a developer edits a deeply nested element, Turbopack doesn’t re-bundle your entire software and even your entire route. It recomputes solely the features affected by the change and sends a minimal replace to the browser. In follow, this implies enhancing a element 5 ranges deep in a element tree usually produces a browser replace in beneath 200ms for single-file edits, slightly than the multi-second delay frequent in giant Webpack initiatives.
To measure this your self, open the browser devtools Community panel, filter by HMR occasions, edit a deeply nested element, and observe the elapsed milliseconds between save and replace. The distinction is most noticeable on initiatives with a whole bunch of modules.
Enhancing a element 5 ranges deep in a element tree usually produces a browser replace in beneath 200ms for single-file edits, slightly than the multi-second delay frequent in giant Webpack initiatives.
Massive Codebase Concerns
Pace good points from Turbopack scale non-linearly with undertaking measurement. A small undertaking with 20 routes and minimal dependencies may even see beneath 20% enchancment, as a result of Webpack was already quick sufficient. Tasks with 500+ routes, deep element bushes, and a posh dependency graph are the place Turbopack’s lazy bundling and function-level caching present the biggest hole. To quantify this on your codebase, run the cold-start benchmark on each a small route subset and the complete undertaking, then examine the ratios. The important thing components are route rely, element tree depth, and the full variety of nodes within the dependency graph.
Configuring Turbopack for Your Stack
Customized Webpack Configurations: What Carries Over
Turbopack offers its personal config keys beneath turbopack in subsequent.config.js. This key requires Subsequent.js 15. Confirm your put in model with npm ls subsequent to substantiate the hot button is acknowledged — if you happen to see an “Invalid subsequent.config.js possibility” warning on startup, seek the advice of the Subsequent.js docs on your particular model’s config construction. Widespread Webpack customizations like loader guidelines and path aliases translate to this new construction:
const path = require('path');
const nextConfig = {
turbopack: {
guidelines: {
'**/*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
resolveAlias: {
'@elements': path.resolve(__dirname, './src/elements'),
'@utils': path.resolve(__dirname, './src/utils'),
},
},
};
module.exports = nextConfig;
This instance demonstrates two of the commonest migration wants: dealing with SVG imports by a loader and configuring path aliases. The guidelines key replaces Webpack’s module.guidelines for specifying loaders, whereas resolveAlias replaces resolve.alias. Word that @svgr/webpack is a Webpack-specific loader; confirm its compatibility with Turbopack’s loader interface earlier than counting on it in your undertaking. If points come up, think about @svgr/rollup or a local Turbopack remodel as alternate options. The resolveAlias values should be absolute paths — use path.resolve(__dirname, '...') slightly than naked relative strings, which resolve towards an inside working listing and produce silent module-not-found failures.
Dealing with Unsupported Webpack Plugins
Turbopack doesn’t assist plugins that deeply hook into Webpack’s compilation lifecycle, equivalent to webpack-bundle-analyzer or customized plugins utilizing compiler.hooks. For initiatives that depend upon these throughout growth, the swish fallback is sustaining a second script in package deal.json:
{
"scripts": {
"dev": "subsequent dev --turbo",
"dev:webpack": "subsequent dev"
}
}
This permits builders to drop again to Webpack for particular edge instances with out abandoning Turbopack because the default growth expertise.
Setting Variables and Function Flags
Setting variable dealing with through .env, .env.native, .env.growth, and .env.check information works identically beneath Turbopack. Turbopack resolves .env information in the identical order as Webpack and handles the NEXT_PUBLIC_ prefix identically. That mentioned, verifying surroundings variable availability within the browser after switching to Turbopack is a worthwhile smoke check, significantly for initiatives that depend on build-time variable inlining.
Manufacturing Readiness: The place Turbopack Stands At this time
subsequent dev --turbo vs. subsequent construct --turbo
The vital distinction: subsequent dev --turbo is steady and examined. subsequent construct --turbo is in energetic growth and should still carry experimental or alpha standing. This implies manufacturing builds presently nonetheless use Webpack. This cut up works nice in follow. The event bundler and the manufacturing bundler don’t have to be the identical instrument, and Subsequent.js has all the time maintained separate optimization paths for dev and construct. Builders get Turbopack’s velocity throughout iteration whereas manufacturing output continues to make use of Webpack’s mature optimization pipeline.
CI/CD Pipeline Changes
CI/CD configurations ought to use Turbopack for growth server duties (working assessments towards the dev server, smoke assessments) whereas preserving the usual construct for manufacturing artifacts. Make sure the dev script in package deal.json consists of the --turbo flag (as proven within the migration part above), since Turbopack is activated through the CLI flag, not through surroundings variables:
title: CI
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-newest
steps:
- makes use of: actions/checkout@v4
- makes use of: actions/setup-node@v4
with:
node-version: '18.18.0'
cache: 'npm'
- run: npm ci
- run: |
npm run dev -- --port 3099 &
echo $! > /tmp/dev.pid
shell: bash
- run: npx wait-on --timeout 60000 http://localhost:3099
- run: npm check
- title: Cleanup dev server
if: all the time()
run: kill $(cat /tmp/dev.pid) 2>/dev/null || true
construct:
runs-on: ubuntu-newest
steps:
- makes use of: actions/checkout@v4
- makes use of: actions/setup-node@v4
with:
node-version: '18.18.0'
cache: 'npm'
- run: npm ci
- run: npm run construct
This workflow runs assessments towards the Turbopack dev server for velocity whereas the manufacturing construct step makes use of Webpack for stability. The dev server course of PID is captured so cleanup runs reliably even when a previous step fails.
Testing Parity
Run your full check suite beneath Turbopack’s dev server earlier than committing to the change. The purpose is surfacing any bundler-specific variations. Widespread gotchas embrace dynamic imports that behave in another way beneath lazy bundling (for instance, a dynamic(() => import(...)) name might resolve in a special chunk order, inflicting hydration mismatches in assessments), customized Babel transforms that want SWC equivalents, and CSS-in-JS libraries (significantly styled-components and Emotion) that require particular SWC remodel settings in subsequent.config.js slightly than Babel plugins.
Troubleshooting Widespread Points
“Module Not Discovered” After Enabling Turbopack
For those who see Module not discovered: Cannot resolve '@elements/...' instantly after switching, the issue is nearly all the time path alias decision. Turbopack resolves aliases from tsconfig.json (or jsconfig.json) paths, however delicate variations in how wildcards and base URLs are interpreted could cause modules to go unresolved. Confirm that tsconfig.json paths match precisely what Turbopack expects, together with trailing /* patterns on listing aliases. Additionally be sure that any resolveAlias entries in subsequent.config.js use absolute paths (through path.resolve(__dirname, '...')) slightly than naked relative strings.
Styling Breakages
Test these so as: CSS Modules and Tailwind CSS v3.x work with Turbopack with out extra configuration. Tailwind CSS v4 customers ought to confirm PostCSS plugin compatibility, as v4 makes use of a special configuration mannequin. Sass requires confirming that the loader is configured beneath the turbopack.guidelines key in subsequent.config.js. For styled-components or Emotion, confirm that the SWC remodel settings are enabled in subsequent.config.js beneath the compiler key, as Turbopack makes use of SWC slightly than Babel for these transforms.
Third-Occasion Bundle Incompatibilities
When a package deal fails silently or throws an unfamiliar error, allow diagnostic tracing first. Setting NEXT_TURBOPACK_TRACING=1 earlier than launching the dev server produces hint logs that assist establish which module or remodel is failing. If no hint output seems, seek the advice of the Turbopack troubleshooting docs for the present variable title, as it might change throughout variations. Report confirmed incompatibilities to the Turbopack GitHub repository to assist the workforce prioritize fixes.
Full Implementation Guidelines
- Affirm Subsequent.js 15+ and Node.js 18.18.0+ are put in.
- Replace the
package deal.jsondev script tosubsequent dev --turbo. - Migrate customized Webpack loaders to the
subsequent.config.jsturbopackkey, verifying every loader’s Turbopack compatibility individually. - Confirm Turbopack activation by checking for “Turbopack prepared” in terminal output.
- Benchmark chilly begin and HMR towards the Webpack baseline utilizing timed runs.
- Run the complete check suite beneath the Turbopack dev server and diff the outcomes towards your Webpack check output.
- Audit third-party packages for compatibility; allow
NEXT_TURBOPACK_TRACINGfor diagnostics. - Replace CI/CD pipelines: Turbopack for dev/check steps, commonplace construct for manufacturing.
- Monitor
subsequent construct --turbogrowth progress for future full adoption. - Doc any fallback configurations and recognized incompatibilities for the workforce so the following particular person doesn’t rediscover them.
Abstract and Subsequent Steps
Turbopack in Subsequent.js 15 delivers measurable velocity wins the place they matter most: chilly begin instances lowered by as much as 76% in accordance with Vercel’s benchmarks (see turbo.construct/pack/docs/benchmarks for methodology), sub-200ms HMR for single-file edits by incremental computation, and a noticeably quicker suggestions loop throughout growth. Use Turbopack for growth at this time, preserve Webpack for manufacturing builds till subsequent construct --turbo reaches steady, and benchmark towards your individual undertaking baselines slightly than counting on generic numbers.
Use Turbopack for growth at this time, preserve Webpack for manufacturing builds till
subsequent construct --turboreaches steady, and benchmark towards your individual undertaking baselines slightly than counting on generic numbers.
Begin right here: run npx subsequent dev --turbo, open your largest web page, and time the chilly begin towards your present Webpack baseline.
