Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply Next.js best practices for RSC boundaries, async APIs, routing, metadata, and optimization.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
bundling.md
1# Bundling23Fix common bundling issues with third-party packages.45## Server-Incompatible Packages67Some packages use browser APIs (`window`, `document`, `localStorage`) and fail in Server Components.89### Error Signs1011```12ReferenceError: window is not defined13ReferenceError: document is not defined14ReferenceError: localStorage is not defined15Module not found: Can't resolve 'fs'16```1718### Solution 1: Mark as Client-Only1920If the package is only needed on client:2122```tsx23// Bad: Fails - package uses window24import SomeChart from 'some-chart-library'2526export default function Page() {27return <SomeChart />28}2930// Good: Use dynamic import with ssr: false31import dynamic from 'next/dynamic'3233const SomeChart = dynamic(() => import('some-chart-library'), {34ssr: false,35})3637export default function Page() {38return <SomeChart />39}40```4142### Solution 2: Externalize from Server Bundle4344For packages that should run on server but have bundling issues:4546```js47// next.config.js48module.exports = {49serverExternalPackages: ['problematic-package'],50}51```5253Use this for:54- Packages with native bindings (sharp, bcrypt)55- Packages that don't bundle well (some ORMs)56- Packages with circular dependencies5758### Solution 3: Client Component Wrapper5960Wrap the entire usage in a client component:6162```tsx63// components/ChartWrapper.tsx64'use client'6566import { Chart } from 'chart-library'6768export function ChartWrapper(props) {69return <Chart {...props} />70}7172// app/page.tsx (server component)73import { ChartWrapper } from '@/components/ChartWrapper'7475export default function Page() {76return <ChartWrapper data={data} />77}78```7980## CSS Imports8182Import CSS files instead of using `<link>` tags. Next.js handles bundling and optimization.8384```tsx85// Bad: Manual link tag86<link rel="stylesheet" href="/styles.css" />8788// Good: Import CSS89import './styles.css'9091// Good: CSS Modules92import styles from './Button.module.css'93```9495## Polyfills9697Next.js includes common polyfills automatically. Don't load redundant ones from polyfill.io or similar CDNs.9899Already included: `Array.from`, `Object.assign`, `Promise`, `fetch`, `Map`, `Set`, `Symbol`, `URLSearchParams`, and 50+ others.100101```tsx102// Bad: Redundant polyfills103<script src="https://polyfill.io/v3/polyfill.min.js?features=fetch,Promise,Array.from" />104105// Good: Next.js includes these automatically106```107108## ESM/CommonJS Issues109110### Error Signs111112```113SyntaxError: Cannot use import statement outside a module114Error: require() of ES Module115Module not found: ESM packages need to be imported116```117118### Solution: Transpile Package119120```js121// next.config.js122module.exports = {123transpilePackages: ['some-esm-package', 'another-package'],124}125```126127## Common Problematic Packages128129| Package | Issue | Solution |130|---------|-------|----------|131| `sharp` | Native bindings | `serverExternalPackages: ['sharp']` |132| `bcrypt` | Native bindings | `serverExternalPackages: ['bcrypt']` or use `bcryptjs` |133| `canvas` | Native bindings | `serverExternalPackages: ['canvas']` |134| `recharts` | Uses window | `dynamic(() => import('recharts'), { ssr: false })` |135| `react-quill` | Uses document | `dynamic(() => import('react-quill'), { ssr: false })` |136| `mapbox-gl` | Uses window | `dynamic(() => import('mapbox-gl'), { ssr: false })` |137| `monaco-editor` | Uses window | `dynamic(() => import('@monaco-editor/react'), { ssr: false })` |138| `lottie-web` | Uses document | `dynamic(() => import('lottie-react'), { ssr: false })` |139140## Bundle Analysis141142Analyze bundle size with the built-in analyzer (Next.js 16.1+):143144```bash145next experimental-analyze146```147148This opens an interactive UI to:149- Filter by route, environment (client/server), and type150- Inspect module sizes and import chains151- View treemap visualization152153Save output for comparison:154155```bash156next experimental-analyze --output157# Output saved to .next/diagnostics/analyze158```159160Reference: https://nextjs.org/docs/app/guides/package-bundling161162## Migrating from Webpack to Turbopack163164Turbopack is the default bundler in Next.js 15+. If you have custom webpack config, migrate to Turbopack-compatible alternatives:165166```js167// next.config.js168module.exports = {169// Good: Works with Turbopack170serverExternalPackages: ['package'],171transpilePackages: ['package'],172173// Bad: Webpack-only - migrate away from this174webpack: (config) => {175// custom webpack config176},177}178```179180Reference: https://nextjs.org/docs/app/building-your-application/upgrading/from-webpack-to-turbopack181