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 595561 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 1666 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 11 K - Application performance monitoring for Node.js apps.
- @aws-sdk/client-s3 34443 K - AWS SDK client for Amazon S3 service.
- @aws-sdk/s3-presigned-post 1176 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 2258 K - State-of-the-art machine learning models for NLP.
- @jpg-store/lucid-cardano 0 K - Library for interacting with Cardano blockchain.
- @libsql/client 1788 K - Lightweight SQL client library.
- @mikro-orm/core 815 K - Core package of MikroORM, a TypeScript ORM.
- @mikro-orm/knex 462 K - MikroORM integration with Knex query builder.
- @node-rs/argon2 746 K - Node.js bindings for the Argon2 password hashing algorithm.
- @node-rs/bcrypt 246 K - Node.js bindings for bcrypt password hashing.
- @prisma/client 12885 K - Auto-generated database client from Prisma schema.
- @react-pdf/renderer 4312 K - React renderer to create PDF files.
- @sentry/profiling-node 1956 K - Performance profiling integration for Node.js with Sentry.
- @sparticuz/chromium 1776 K - Chromium binaries for serverless and container environments.
- @swc/core 35415 K - Super-fast JavaScript/TypeScript compiler written in Rust.
- @xenova/transformers 536 K - Transformers models for JavaScript and TypeScript.
- argon2 1732 K - Password hashing library implementing Argon2.
- autoprefixer 54979 K - PostCSS plugin to parse CSS and add vendor prefixes.
- aws-crt 608 K - AWS Common Runtime bindings for performance improvements.
- bcrypt 4873 K - Library to hash passwords using bcrypt algorithm.
- better-sqlite3 6859 K - Fast SQLite3 bindings for Node.js.
- canvas 6938 K - Node.js canvas implementation for drawing graphics.
- chromadb-default-embed 7 K - Default embeddings for Chroma vector database.
- config 1390 K - Node.js configuration management tool.
- cpu-features 7345 K - Detect CPU features in Node.js.
- cypress 6431 K - End-to-end testing framework.
- dd-trace 6690 K - Datadog tracing client for Node.js.
- eslint 135094 K - Pluggable JavaScript linter.
- express 109882 K - Fast, minimalist web framework for Node.js.
- firebase-admin 5910 K - Firebase admin SDK for server-side applications.
- import-in-the-middle 63530 K - Module to hook into imports for instrumentation.
- isolated-vm 1006 K - Isolated JavaScript VMs for Node.js.
- jest 39501 K - JavaScript testing framework.
- jsdom 79674 K - JavaScript implementation of the DOM and HTML standards.
- keyv 110150 K - Simple key-value storage with multiple backends.
- libsql 1874 K - Lightweight SQL database client.
- mdx-bundler 164 K - Bundle MDX files using esbuild.
- mongodb 12789 K - Official MongoDB driver for Node.js.
- mongoose 5601 K - MongoDB object modeling tool for Node.js.
- msw 13497 K - Mock Service Worker for API mocking in tests and development.
- ngrok 99 K - Secure tunnels to localhost.
- next 45882 K - React framework for server-side rendering and static sites.
- next-auth 5060 K - Authentication library for Next.js.
- next-pwa 252 K - PWA plugin for Next.js to add offline support.
- next-sitemap 424 K - Sitemap generator for Next.js projects.
- next-themes 22466 K - Theme management for Next.js with dark mode support.
- node-fetch 124370 K - A light-weight module that brings window.fetch to Node.js.
- nodemailer 16956 K - Module to send emails from Node.js.
- nuxt 1676 K - Vue.js framework for SSR and static sites.
- prisma 13863 K - Next-generation ORM for Node.js and TypeScript.
- react 115574 K - JavaScript library for building user interfaces.
- react-dom 135787 K - Entry point to the DOM and server renderers for React.
- redis 11040 K - Redis client for Node.js.
- swr 13457 K - React Hooks for data fetching.
- ts-node 41171 K - TypeScript execution environment for Node.js.
- typescript 180404 K - TypeScript language compiler.
- uuid 190389 K - Simple, fast generation of RFC4122 UUIDs.
- webpack 47411 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.