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 299393 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 1449 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 12 K - Application performance monitoring for Node.js apps.
- @aws-sdk/client-s3 9903 K - AWS SDK client for Amazon S3 service.
- @aws-sdk/s3-presigned-post 343 K - Generate presigned POST data for S3 uploads.
- @blockfrost/blockfrost-js 11 K - JavaScript SDK for the Blockfrost Cardano API.
- @highlight-run/node 12 K - Real-time error monitoring and session replay for Node.js.
- @huggingface/transformers 74 K - State-of-the-art machine learning models for NLP.
- @jpg-store/lucid-cardano 0 K - Library for interacting with Cardano blockchain.
- @libsql/client 180 K - Lightweight SQL client library.
- @mikro-orm/core 239 K - Core package of MikroORM, a TypeScript ORM.
- @mikro-orm/knex 228 K - MikroORM integration with Knex query builder.
- @node-rs/argon2 138 K - Node.js bindings for the Argon2 password hashing algorithm.
- @node-rs/bcrypt 139 K - Node.js bindings for bcrypt password hashing.
- @prisma/client 2793 K - Auto-generated database client from Prisma schema.
- @react-pdf/renderer 801 K - React renderer to create PDF files.
- @sentry/profiling-node 809 K - Performance profiling integration for Node.js with Sentry.
- @sparticuz/chromium 206 K - Chromium binaries for serverless and container environments.
- @swc/core 13544 K - Super-fast JavaScript/TypeScript compiler written in Rust.
- @xenova/transformers 101 K - Transformers models for JavaScript and TypeScript.
- argon2 348 K - Password hashing library implementing Argon2.
- autoprefixer 27944 K - PostCSS plugin to parse CSS and add vendor prefixes.
- aws-crt 407 K - AWS Common Runtime bindings for performance improvements.
- bcrypt 2142 K - Library to hash passwords using bcrypt algorithm.
- better-sqlite3 1235 K - Fast SQLite3 bindings for Node.js.
- canvas 3653 K - Node.js canvas implementation for drawing graphics.
- chromadb-default-embed 26 K - Default embeddings for Chroma vector database.
- config 1400 K - Node.js configuration management tool.
- cpu-features 3455 K - Detect CPU features in Node.js.
- cypress 6080 K - End-to-end testing framework.
- dd-trace 3448 K - Datadog tracing client for Node.js.
- eslint 57212 K - Pluggable JavaScript linter.
- express 41539 K - Fast, minimalist web framework for Node.js.
- firebase-admin 2175 K - Firebase admin SDK for server-side applications.
- import-in-the-middle 13630 K - Module to hook into imports for instrumentation.
- isolated-vm 242 K - Isolated JavaScript VMs for Node.js.
- jest 30105 K - JavaScript testing framework.
- jsdom 31128 K - JavaScript implementation of the DOM and HTML standards.
- keyv 49287 K - Simple key-value storage with multiple backends.
- libsql 179 K - Lightweight SQL database client.
- mdx-bundler 90 K - Bundle MDX files using esbuild.
- mongodb 6657 K - Official MongoDB driver for Node.js.
- mongoose 3215 K - MongoDB object modeling tool for Node.js.
- msw 5183 K - Mock Service Worker for API mocking in tests and development.
- ngrok 159 K - Secure tunnels to localhost.
- next 10463 K - React framework for server-side rendering and static sites.
- next-auth 1478 K - Authentication library for Next.js.
- next-pwa 170 K - PWA plugin for Next.js to add offline support.
- next-sitemap 392 K - Sitemap generator for Next.js projects.
- next-themes 5532 K - Theme management for Next.js with dark mode support.
- node-fetch 65873 K - A light-weight module that brings window.fetch to Node.js.
- nodemailer 5381 K - Module to send emails from Node.js.
- nuxt 848 K - Vue.js framework for SSR and static sites.
- prisma 3649 K - Next-generation ORM for Node.js and TypeScript.
- react 39095 K - JavaScript library for building user interfaces.
- react-dom 37414 K - Entry point to the DOM and server renderers for React.
- redis 4857 K - Redis client for Node.js.
- swr 3978 K - React Hooks for data fetching.
- ts-node 29306 K - TypeScript execution environment for Node.js.
- typescript 82535 K - TypeScript language compiler.
- uuid 148623 K - Simple, fast generation of RFC4122 UUIDs.
- webpack 30886 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.