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 561814 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 1616 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 13 K - Application performance monitoring for Node.js apps.
- @aws-sdk/client-s3 24824 K - AWS SDK client for Amazon S3 service.
- @aws-sdk/s3-presigned-post 905 K - Generate presigned POST data for S3 uploads.
- @blockfrost/blockfrost-js 19 K - JavaScript SDK for the Blockfrost Cardano API.
- @highlight-run/node 10 K - Real-time error monitoring and session replay for Node.js.
- @huggingface/transformers 862 K - State-of-the-art machine learning models for NLP.
- @jpg-store/lucid-cardano 0 K - Library for interacting with Cardano blockchain.
- @libsql/client 888 K - Lightweight SQL client library.
- @mikro-orm/core 580 K - Core package of MikroORM, a TypeScript ORM.
- @mikro-orm/knex 494 K - MikroORM integration with Knex query builder.
- @node-rs/argon2 344 K - Node.js bindings for the Argon2 password hashing algorithm.
- @node-rs/bcrypt 197 K - Node.js bindings for bcrypt password hashing.
- @prisma/client 9382 K - Auto-generated database client from Prisma schema.
- @react-pdf/renderer 2722 K - React renderer to create PDF files.
- @sentry/profiling-node 2005 K - Performance profiling integration for Node.js with Sentry.
- @sparticuz/chromium 822 K - Chromium binaries for serverless and container environments.
- @swc/core 41605 K - Super-fast JavaScript/TypeScript compiler written in Rust.
- @xenova/transformers 390 K - Transformers models for JavaScript and TypeScript.
- argon2 1093 K - Password hashing library implementing Argon2.
- autoprefixer 67499 K - PostCSS plugin to parse CSS and add vendor prefixes.
- aws-crt 788 K - AWS Common Runtime bindings for performance improvements.
- bcrypt 4537 K - Library to hash passwords using bcrypt algorithm.
- better-sqlite3 5801 K - Fast SQLite3 bindings for Node.js.
- canvas 6225 K - Node.js canvas implementation for drawing graphics.
- chromadb-default-embed 14 K - Default embeddings for Chroma vector database.
- config 1673 K - Node.js configuration management tool.
- cpu-features 6653 K - Detect CPU features in Node.js.
- cypress 7167 K - End-to-end testing framework.
- dd-trace 6913 K - Datadog tracing client for Node.js.
- eslint 127565 K - Pluggable JavaScript linter.
- express 95339 K - Fast, minimalist web framework for Node.js.
- firebase-admin 5686 K - Firebase admin SDK for server-side applications.
- import-in-the-middle 50973 K - Module to hook into imports for instrumentation.
- isolated-vm 732 K - Isolated JavaScript VMs for Node.js.
- jest 41761 K - JavaScript testing framework.
- jsdom 69724 K - JavaScript implementation of the DOM and HTML standards.
- keyv 118777 K - Simple key-value storage with multiple backends.
- libsql 945 K - Lightweight SQL database client.
- mdx-bundler 175 K - Bundle MDX files using esbuild.
- mongodb 11286 K - Official MongoDB driver for Node.js.
- mongoose 5007 K - MongoDB object modeling tool for Node.js.
- msw 15482 K - Mock Service Worker for API mocking in tests and development.
- ngrok 131 K - Secure tunnels to localhost.
- next 34650 K - React framework for server-side rendering and static sites.
- next-auth 3780 K - Authentication library for Next.js.
- next-pwa 282 K - PWA plugin for Next.js to add offline support.
- next-sitemap 543 K - Sitemap generator for Next.js projects.
- next-themes 30345 K - Theme management for Next.js with dark mode support.
- node-fetch 133785 K - A light-weight module that brings window.fetch to Node.js.
- nodemailer 13067 K - Module to send emails from Node.js.
- nuxt 1327 K - Vue.js framework for SSR and static sites.
- prisma 10394 K - Next-generation ORM for Node.js and TypeScript.
- react 125172 K - JavaScript library for building user interfaces.
- react-dom 117927 K - Entry point to the DOM and server renderers for React.
- redis 9128 K - Redis client for Node.js.
- swr 10283 K - React Hooks for data fetching.
- ts-node 41490 K - TypeScript execution environment for Node.js.
- typescript 184568 K - TypeScript language compiler.
- uuid 241810 K - Simple, fast generation of RFC4122 UUIDs.
- webpack 44748 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.