MENU
Packaging Configurations
1. optimizePackageImports
The optimizePackageImports feature helps improve performance by loading only the modules you actually use from large packages, while still allowing convenient import syntax with many named exports.
module.exports = {
experimental: {
optimizePackageImports: [
'lodash',
'react-icons',
'@mui/material',
'date-fns'
],
},
}
Without optimization, importing from large packages can be expensive:
// This might bundle the entire lodash library
import { debounce, throttle } from 'lodash'
// With optimization, only debounce and throttle are bundled
import { debounce, throttle } from 'lodash'
The following libraries are optimized by default:
- lucide-react, date-fns, lodash-es
- @mui/material, @mui/icons-material
- react-icons/*, @heroicons/react
- antd, @ant-design/icons
- recharts, @tremor/react
This optimization is particularly valuable for:
- Reducing bundle size in production
- Faster development builds
- Improved time-to-interactive metrics
- Better tree-shaking results
2. output
The output configuration controls how Next.js builds and packages your application. The most important option is standalone, which creates a self-contained deployment package.
module.exports = {
output: 'standalone',
}
This creates a .next/standalone folder containing:
- A minimal Node.js server (server.js)
- Only the necessary files for production
- Traced dependencies from node_modules
- All required application code
Manual deployment steps after build:
# Copy static assets
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/
# Start the server
cd .next/standalone
PORT=8080 HOSTNAME=0.0.0.0 node server.js
Advanced configuration for monorepos:
const path = require('path')
module.exports = {
output: 'standalone',
outputFileTracingRoot: path.join(__dirname, '../../'),
outputFileTracingExcludes: {
'/api/heavy-endpoint': ['./large-unused-deps/**/*'],
},
outputFileTracingIncludes: {
'/api/special': ['./required-native-deps/**/*'],
},
}
(understand minimatch format here 810246 K )
Benefits of standalone output:
- Smaller Docker images (no need for full node_modules)
- Faster deployment times
- Reduced security surface area
- Simplified containerization
Next.js uses @vercel/nft 1672 during next build to analyze and trace all files a page might need, including imports, require, and fs usage. The production server's dependencies are recorded in .next/next-server.js.nft.json. You can use these .nft.json files to identify and copy the required files for deployment.
3. serverExternalPackages
The serverExternalPackages option allows you to exclude specific dependencies from Next.js's automatic bundling for Server Components and Route Handlers, forcing them to use native Node.js require instead.
/** @type {import('next').NextConfig} */
const nextConfig = {
serverExternalPackages: [
'@acme/native-module',
'sharp',
'canvas',
'sqlite3'
],
}
module.exports = nextConfig
This is necessary when packages:
- Use Node.js-specific features that don't work when bundled
- Include native binaries or native modules
- Have complex dependency chains that break during bundling
- Use dynamic imports or filesystem operations
Common packages that benefit from external bundling:
- Database drivers: Prisma, MongoDB, PostgreSQL clients
- Image processing: Sharp, Canvas, ImageMagick bindings
- Cryptography: bcrypt, argon2, native crypto libraries
- Native modules: Node-gyp compiled packages
At the time of writing, these packages are automatically opted out of full Turbopack compatibility while maintainers work on fixes.
- @appsignal/nodejs 19 K - Application performance monitoring for Node.js apps.
- @aws-sdk/client-s3 50072 K - AWS SDK client for Amazon S3 service.
- @aws-sdk/s3-presigned-post 2350 K - Generate presigned POST data for S3 uploads.
- @blockfrost/blockfrost-js 18 K - JavaScript SDK for the Blockfrost Cardano API.
- @highlight-run/node 13 K - Real-time error monitoring and session replay for Node.js.
- @huggingface/transformers 3674 K - State-of-the-art machine learning models for NLP.
- @jpg-store/lucid-cardano 0 K - Library for interacting with Cardano blockchain.
- @libsql/client 3233 K - Lightweight SQL client library.
- @mikro-orm/core 1073 K - Core package of MikroORM, a TypeScript ORM.
- @mikro-orm/knex 757 K - MikroORM integration with Knex query builder.
- @node-rs/argon2 1482 K - Node.js bindings for the Argon2 password hashing algorithm.
- @node-rs/bcrypt 328 K - Node.js bindings for bcrypt password hashing.
- @prisma/client 18268 K - Auto-generated database client from Prisma schema.
- @react-pdf/renderer 6489 K - React renderer to create PDF files.
- @sentry/profiling-node 3341 K - Performance profiling integration for Node.js with Sentry.
- @sparticuz/chromium 2556 K - Chromium binaries for serverless and container environments.
- @swc/core 48089 K - Super-fast JavaScript/TypeScript compiler written in Rust.
- @xenova/transformers 591 K - Transformers models for JavaScript and TypeScript.
- argon2 2526 K - Password hashing library implementing Argon2.
- autoprefixer 75425 K - PostCSS plugin to parse CSS and add vendor prefixes.
- aws-crt 862 K - AWS Common Runtime bindings for performance improvements.
- bcrypt 7000 K - Library to hash passwords using bcrypt algorithm.
- better-sqlite3 12107 K - Fast SQLite3 bindings for Node.js.
- canvas 8981 K - Node.js canvas implementation for drawing graphics.
- chromadb-default-embed 13 K - Default embeddings for Chroma vector database.
- config 1987 K - Node.js configuration management tool.
- cpu-features 13862 K - Detect CPU features in Node.js.
- cypress 7209 K - End-to-end testing framework.
- dd-trace 10945 K - Datadog tracing client for Node.js.
- eslint 184880 K - Pluggable JavaScript linter.
- express 157688 K - Fast, minimalist web framework for Node.js.
- firebase-admin 9962 K - Firebase admin SDK for server-side applications.
- import-in-the-middle 87647 K - Module to hook into imports for instrumentation.
- isolated-vm 1140 K - Isolated JavaScript VMs for Node.js.
- jest 54916 K - JavaScript testing framework.
- jsdom 117138 K - JavaScript implementation of the DOM and HTML standards.
- keyv 188732 K - Simple key-value storage with multiple backends.
- libsql 3469 K - Lightweight SQL database client.
- mdx-bundler 271 K - Bundle MDX files using esbuild.
- mongodb 16712 K - Official MongoDB driver for Node.js.
- mongoose 7679 K - MongoDB object modeling tool for Node.js.
- msw 23340 K - Mock Service Worker for API mocking in tests and development.
- ngrok 200 K - Secure tunnels to localhost.
- next 66691 K - React framework for server-side rendering and static sites.
- next-auth 6785 K - Authentication library for Next.js.
- next-pwa 271 K - PWA plugin for Next.js to add offline support.
- next-sitemap 695 K - Sitemap generator for Next.js projects.
- next-themes 30497 K - Theme management for Next.js with dark mode support.
- node-fetch 226012 K - A light-weight module that brings window.fetch to Node.js.
- nodemailer 25677 K - Module to send emails from Node.js.
- nuxt 2379 K - Vue.js framework for SSR and static sites.
- prisma 19011 K - Next-generation ORM for Node.js and TypeScript.
- react 203950 K - JavaScript library for building user interfaces.
- react-dom 192489 K - Entry point to the DOM and server renderers for React.
- redis 15484 K - Redis client for Node.js.
- swr 19234 K - React Hooks for data fetching.
- ts-node 53529 K - TypeScript execution environment for Node.js.
- typescript 328873 K - TypeScript language compiler.
- uuid 330366 K - Simple, fast generation of RFC4122 UUIDs.
- webpack 66003 K - Module bundler for JavaScript.
4. transpilePackages
The transpilePackages option allows Next.js to automatically transpile and bundle dependencies from local packages (monorepos) or external dependencies that need compilation.
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: [
'@my-company/shared-components',
'@my-company/utils',
'some-es6-only-package'
],
}
module.exports = nextConfig
This replaces the need for next-transpile-modules and is useful for:
// Monorepo structure
my-monorepo/
├── apps/
│ └── web/ // Next.js app
├── packages/
│ ├── ui/ // Shared UI components
│ ├── utils/ // Shared utilities
│ └── config/ // Shared configuration
// Configuration for the web app
module.exports = {
transpilePackages: ['@my-company/ui', '@my-company/utils'],
}
Common use cases:
- Monorepos: Transpiling local packages that aren't pre-built
- ESM-only packages: Converting ES modules to CommonJS when needed
- TypeScript packages: Compiling TypeScript source in node_modules
- Modern JavaScript: Transpiling packages using newer syntax
Example with a shared UI library:
// packages/ui/package.json
{
"name": "@my-company/ui",
"main": "src/index.ts", // Points to source, not dist
"exports": {
".": "./src/index.ts"
}
}
// apps/web/next.config.js
module.exports = {
transpilePackages: ['@my-company/ui'],
}
5. turbotrace
Tracing dependencies can be slow because it requires very complex computations and analysis. Next.js created turbotrace in Rust as a faster and smarter alternative to the JavaScript implementation for dependency tracing.
Dependency tracing is crucial for Next.js to understand which files and modules your application depends on, especially during the build process and for features like static optimization. The traditional JavaScript-based tracing can become a performance bottleneck in large applications with complex dependency graphs.
To enable turbotrace, you can add the following experimental configuration to your next.config.js:
module.exports = {
experimental: {
turbotrace: {
logLevel: 'warning',
logDetail: false,
logAll: false,
contextDirectory: process.cwd(),
processCwd: process.cwd(),
memoryLimit: 6000
},
},
}
logLevel - Controls the verbosity of turbotrace logging output. Default is 'error'.
turbotrace: {
logLevel: 'info' // 'bug' | 'fatal' | 'error' | 'warning' | 'hint' | 'note' | 'suggestions' | 'info'
}
Use more verbose levels like 'info' or 'suggestions' during development to understand what turbotrace is doing, but keep it at 'error' or 'warning' in production to avoid log noise.
logDetail - Controls whether turbotrace logs should include detailed analysis information. Default is false.
turbotrace: {
logDetail: true
}
Enable this when debugging dependency tracing issues or when you need to understand the specific details of what files are being analyzed.
logAll - Shows all log messages without limit. By default, turbotrace only shows 1 log message per category.
turbotrace: {
logAll: true
}
Useful for comprehensive debugging, but can generate significant log output in large projects.
contextDirectory - Controls the context directory for turbotrace analysis. Files outside this directory will not be traced.
turbotrace: {
contextDirectory: '/path/to/your/project'
}
This option has the same effect as setting outputFileTracingRoot. If both are set, experimental.turbotrace.contextDirectory takes precedence. Use this to limit tracing scope and improve performance by excluding unnecessary directories.
processCwd - Specifies the value of process.cwd() for tracing purposes when your code contains process.cwd() expressions.
turbotrace: {
processCwd: '/path/to/working/directory'
}
For example, if your code has require(process.cwd() + '/package.json'), turbotrace will trace it as require('/path/to/working/directory/package.json'). This ensures accurate dependency resolution when process.cwd() is used dynamically.
memoryLimit - Controls the maximum memory usage of turbotrace in MB. Default is 6000 MB (6 GB).
turbotrace: {
memoryLimit: 4000 // Limit to 4 GB
}
Adjust this based on your system's available memory and the size of your project. Larger projects with complex dependency graphs may need higher limits, while smaller projects or memory-constrained environments may benefit from lower limits.
Turbotrace significantly improves build performance for large Next.js applications by leveraging Rust's performance advantages for complex dependency analysis. Monitor your build times and memory usage when enabling this feature to ensure optimal configuration for your specific project needs.
6. urlImports
The urlImports feature allows you to import modules directly from external URLs instead of installing them locally. This experimental feature requires explicit configuration of trusted domains.
module.exports = {
experimental: {
urlImports: [
'https://cdn.skypack.dev',
'https://esm.sh',
'https://cdn.jsdelivr.net',
'https://unpkg.com'
],
},
}
Once configured, you can import modules directly from URLs:
// Import from Skypack CDN
import confetti from 'https://cdn.skypack.dev/canvas-confetti'
import { format } from 'https://cdn.skypack.dev/date-fns'
// Import from esm.sh
import React from 'https://esm.sh/react@18'
// Use in components
export default function CelebrationPage() {
const celebrate = () => {
confetti({
particleCount: 100,
spread: 70,
origin: { y: 0.6 }
})
}
return (
<div>
<h1>Today is {format(new Date(), 'MMMM do, yyyy')}</h1>
<button onClick={celebrate}>Celebrate!</button>
</div>
)
}
URL imports work in various contexts:
// Static image imports
import logo from 'https://example.com/assets/logo.png'
// CSS imports
import 'https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css'
// Dynamic imports
const module = await import('https://cdn.skypack.dev/lodash-es')
// Asset imports with import.meta.url
const configUrl = new URL('https://example.com/config.json', import.meta.url)
const config = await fetch(configUrl).then(r => r.json())
Next.js creates a lockfile system:
- Downloads and caches URL imports in next.lock/ directory
- Commits the lockfile to Git for reproducible builds
- Uses cached versions in production builds
- Fetches updates only when explicitly requested
Security considerations:
- Only use trusted CDNs and domains
- Verify the integrity of imported modules
- Consider supply chain security implications
- Use specific version URLs when possible
The feature supports resources with Cache-Control: no-cache headers, which are fetched fresh on each build, making it suitable for dynamic configuration or frequently updated assets.