# Next.js Optimization
Performance optimization techniques for images, fonts, scripts, and bundles.
## Image Optimization
### Next.js Image Component
Automatic optimization with modern formats (WebP, AVIF):
```tsx
import Image from 'next/image'
export default function Page() {
return (
<>
{/* Local image */}
{/* Remote image */}
{/* Responsive fill */}
{/* With blur placeholder */}
>
)
}
```
### Image Props Reference
**Required:**
- `src` - Image path (string or static import)
- `alt` - Alt text for accessibility
- `width`, `height` - Dimensions (required unless using `fill`)
**Optional:**
- `fill` - Fill parent container (makes width/height optional)
- `sizes` - Responsive sizes hint for srcset
- `quality` - 1-100 (default 75)
- `priority` - Disable lazy loading, preload image
- `placeholder` - 'blur' | 'empty' (default 'empty')
- `blurDataURL` - Data URL for blur placeholder
- `loading` - 'lazy' | 'eager' (default 'lazy')
- `style` - CSS styles
- `className` - CSS class
- `onLoad` - Callback when loaded
### Responsive Images with Sizes
```tsx
```
This tells browser:
- Mobile (<768px): Use 100% viewport width
- Tablet (768-1200px): Use 50% viewport width
- Desktop (>1200px): Use 33% viewport width
### Static Import for Local Images
```tsx
import heroImage from '@/public/hero.jpg'
```
### Remote Image Configuration
```js
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
pathname: '/images/**',
},
{
protocol: 'https',
hostname: 'cdn.example.com',
}
],
// Device sizes for srcset
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
// Image sizes for srcset
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
// Supported formats
formats: ['image/webp'],
// Cache optimization images for 60 days
minimumCacheTTL: 60 * 60 * 24 * 60,
}
}
```
## Font Optimization
### Google Fonts
Automatic optimization with zero layout shift:
```tsx
// app/layout.tsx
import { Inter, Roboto_Mono, Playfair_Display } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
})
const robotoMono = Roboto_Mono({
subsets: ['latin'],
display: 'swap',
weight: ['400', '700'],
variable: '--font-roboto-mono',
})
const playfair = Playfair_Display({
subsets: ['latin'],
display: 'swap',
weight: ['400', '700', '900'],
style: ['normal', 'italic'],
})
export default function RootLayout({ children }) {
return (
{children}
)
}
```
Use CSS variables:
```css
.code {
font-family: var(--font-roboto-mono);
}
```
### Local Fonts
```tsx
import localFont from 'next/font/local'
const myFont = localFont({
src: [
{
path: './fonts/my-font-regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './fonts/my-font-bold.woff2',
weight: '700',
style: 'normal',
}
],
variable: '--font-my-font',
display: 'swap',
})
export default function RootLayout({ children }) {
return (
{children}
)
}
```
### Font Display Strategies
```tsx
const font = Inter({
display: 'swap', // Show fallback immediately, swap when loaded (recommended)
// display: 'optional', // Only use font if available immediately
// display: 'block', // Hide text until font loads (max 3s)
// display: 'fallback', // Show fallback briefly, swap if loaded quickly
// display: 'auto', // Browser default
})
```
## Script Optimization
### Script Component
Control loading behavior:
```tsx
import Script from 'next/script'
export default function Page() {
return (
<>
{/* Load after page is interactive (recommended for analytics) */}
{/* Load while page is idle (lowest priority) */}
{/* Load before page is interactive (use sparingly) */}
{/* Inline script with strategy */}
{/* With onLoad callback */}