Loading...
Loading...
Best practices and guidelines for Turbopack, the Rust-powered incremental bundler for Next.js and modern web development
npx skill4agent add mindrally/skills turbopack-bundlerproject/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── globals.css
│ ├── components/ # Shared components
│ └── lib/ # Utility functions
├── public/ # Static assets
├── next.config.js # Next.js configuration
├── tsconfig.json # TypeScript config
└── package.json# Next.js 13.4+
next dev --turbo
# Or in package.json
{
"scripts": {
"dev": "next dev --turbo"
}
}// next.config.js
module.exports = {
experimental: {
turbo: {
// Turbopack-specific configuration
}
}
};// next.config.js
module.exports = {
turbopack: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js'
},
'*.mdx': {
loaders: ['@mdx-js/loader']
}
}
}
};// next.config.js
module.exports = {
turbopack: {
resolveAlias: {
'@components': './src/components',
'@lib': './src/lib',
'@styles': './src/styles'
}
}
};// next.config.js
module.exports = {
turbopack: {
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.json']
}
};.module.csscss-loaderpostcss-loaderbabel-loader@babel/preset-env{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["src/components/*"],
"@lib/*": ["src/lib/*"],
"@styles/*": ["src/styles/*"]
}
}
}src/
├── components/
│ ├── atoms/ # Basic building blocks
│ │ ├── Button/
│ │ └── Input/
│ ├── molecules/ # Combinations of atoms
│ │ ├── SearchBar/
│ │ └── NavItem/
│ ├── organisms/ # Complex components
│ │ ├── Header/
│ │ └── Footer/
│ └── templates/ # Page layouts
│ └── MainLayout/
├── app/
│ └── page.tsx
└── lib/
└── utils.tsButton/
├── Button.tsx
├── Button.module.css
├── Button.test.tsx
└── index.tsimport dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('@/components/HeavyComponent'), {
loading: () => <p>Loading...</p>,
ssr: false // Disable server-side rendering if needed
});app/// Split large components
const ChartComponent = dynamic(() => import('./ChartComponent'));
const EditorComponent = dynamic(() => import('./EditorComponent'));// Keep modules focused and small
// Changes to one module don't invalidate others
// Good: Separate concerns
export function formatDate(date: Date) { /* ... */ }
export function formatCurrency(amount: number) { /* ... */ }
// Avoid: Large utility files that change frequently// Prefer specific imports
import { Button } from '@/components/Button';
// Avoid importing entire libraries
// Bad: import _ from 'lodash';
// Good: import debounce from 'lodash/debounce';// Use const assertions for better tree-shaking
const ROUTES = {
home: '/',
about: '/about',
contact: '/contact'
} as const;import styles from './Component.module.css';
function Component() {
return <div className={styles.container}>Content</div>;
}// app/layout.tsx
import './globals.css';// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}'
]
};# .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgresql://...// Client-side (must have NEXT_PUBLIC_ prefix)
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
// Server-side only
const dbUrl = process.env.DATABASE_URL;src/
├── components/
│ └── Button/
│ ├── Button.tsx
│ └── Button.test.tsx # Co-located test
└── __tests__/ # Integration tests
└── pages/
└── home.test.tsx// Ensure correct tsconfig.json paths
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"] // Must match actual structure
}
}
}# Clear Turbopack cache if issues arise
rm -rf .nextNEXT_DEBUG_TURBOPACK=1 next dev --turbo# Check build output
ANALYZE=true next buildtsc --noEmit