Next.js Performance Optimization

Overview

Performance optimization is key to improving user experience. Next.js provides many built-in optimization features and best practices.

Image Optimization

Using the Image Component

import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="/hero.jpg"
      alt="Hero"
      width={1200}
      height={600}
      priority // 优先加载
      placeholder="blur" // 模糊占位符
    />
  )
}

Responsive Images

<Image
  src="/hero.jpg"
  alt="Hero"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  style={{ objectFit: 'cover' }}
/>

Code Splitting

Dynamic Imports

import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() => import('@/components/Heavy'), {
  loading: () => <p>加载中...</p>,
  ssr: false // 禁用 SSR
})

export default function Page() {
  return <DynamicComponent />
}

Conditional Loading

'use client'

import { useState } from 'react'
import dynamic from 'next/dynamic'

const Chart = dynamic(() => import('@/components/Chart'), {
  ssr: false
})

export default function Dashboard() {
  const [showChart, setShowChart] = useState(false)
  
  return (
    <div>
      <button onClick={() => setShowChart(true)}>显示图表</button>
      {showChart && <Chart />}
    </div>
  )
}

Font Optimization

import { Inter } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  preload: true
})

export default function RootLayout({ children }) {
  return (
    <html className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

Caching Strategies

Data Caching

// 静态数据 - 长时间缓存
const data = await fetch('url', {
  next: { revalidate: 3600 }
})

// 动态数据 - 不缓存
const data = await fetch('url', {
  cache: 'no-store'
})

Route Caching

// app/page.tsx
export const revalidate = 3600 // 1小时

export default async function Page() {
  const data = await getData()
  return <div>{data.title}</div>
}

Performance Monitoring

Web Vitals

// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
      </body>
    </html>
  )
}

Custom Monitoring

// app/web-vitals.tsx
'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    console.log(metric)
    // 发送到分析服务
  })
}

Best Practices

1. Use Suspense and Streaming

import { Suspense } from 'react'

export default function Page() {
  return (
    <div>
      <h1>快速内容</h1>
      <Suspense fallback={<Loading />}>
        <SlowComponent />
      </Suspense>
    </div>
  )
}

2. Optimize Third-Party Scripts

import Script from 'next/script'

export default function Page() {
  return (
    <>
      <Script
        src="https://example.com/script.js"
        strategy="lazyOnload" // 延迟加载
      />
    </>
  )
}

3. Reduce JavaScript Bundle Size

// 使用 tree-shaking
import { specific } from 'library'

// 避免导入整个库
// import * as library from 'library'

4. Preload Critical Resources

import Link from 'next/link'

<Link href="/dashboard" prefetch={true}>
  仪表板
</Link>

Previous Chapter: Next.js Testing | Next Chapter: Next.js SEO Optimization