Skip to content

Next.js 最佳实践 ✨

🎯 概述

遵循最佳实践可以提高代码质量、性能和可维护性。

📦 项目结构

推荐结构

app/
  ├── (auth)/
  │   ├── login/
  │   └── register/
  ├── (dashboard)/
  │   ├── layout.tsx
  │   └── page.tsx
  ├── api/
  ├── layout.tsx
  └── page.tsx
components/
  ├── ui/
  ├── forms/
  └── layouts/
lib/
  ├── utils.ts
  ├── db.ts
  └── auth.ts
public/
  ├── images/
  └── fonts/

🚀 性能优化

1. 使用 Server Components

tsx
// ✅ 默认使用服务端组件
export default async function Page() {
  const data = await getData()
  return <div>{data.title}</div>
}

// ❌ 避免不必要的客户端组件
'use client'
export default function Page() {
  return <div>静态内容</div>
}

2. 代码分割

tsx
import dynamic from 'next/dynamic'

const HeavyComponent = dynamic(() => import('@/components/Heavy'), {
  loading: () => <Skeleton />,
  ssr: false,
})

3. 图片优化

tsx
import Image from 'next/image'

<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority
  placeholder="blur"
/>

📝 代码质量

1. TypeScript

tsx
// 使用类型定义
interface User {
  id: string
  name: string
  email: string
}

async function getUser(id: string): Promise<User> {
  const res = await fetch(`/api/users/${id}`)
  return res.json()
}

2. 错误处理

tsx
// app/page.tsx
export default async function Page() {
  try {
    const data = await getData()
    return <div>{data.title}</div>
  } catch (error) {
    return <ErrorComponent error={error} />
  }
}

3. 数据验证

tsx
import { z } from 'zod'

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
})

export async function POST(request: Request) {
  const body = await request.json()
  const result = schema.safeParse(body)
  
  if (!result.success) {
    return Response.json({ error: result.error }, { status: 400 })
  }
  
  // 处理有效数据
}

🎨 SEO 优化

1. 元数据

tsx
export const metadata = {
  title: '页面标题',
  description: '页面描述',
  openGraph: {
    title: '页面标题',
    description: '页面描述',
    images: ['/og-image.jpg'],
  },
}

2. 语义化 HTML

tsx
<article>
  <header>
    <h1>文章标题</h1>
    <time dateTime="2024-01-01">2024年1月1日</time>
  </header>
  <section>
    <p>文章内容</p>
  </section>
</article>

📊 安全性

1. 环境变量

bash
# .env.local
DATABASE_URL="postgresql://..."
JWT_SECRET="your-secret"

# 客户端变量使用 NEXT_PUBLIC_ 前缀
NEXT_PUBLIC_API_URL="https://api.example.com"

2. API 保护

tsx
// middleware.ts
export function middleware(request: Request) {
  const token = request.headers.get('Authorization')
  
  if (!token) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }
  
  return NextResponse.next()
}

3. 输入清理

tsx
import DOMPurify from 'isomorphic-dompurify'

const clean = DOMPurify.sanitize(userInput)

📚 开发体验

1. ESLint 配置

json
{
  "extends": "next/core-web-vitals",
  "rules": {
    "no-console": "warn",
    "@typescript-eslint/no-unused-vars": "error"
  }
}

2. Prettier 配置

json
{
  "semi": false,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5"
}

3. Git Hooks

bash
npm install -D husky lint-staged

# package.json
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"]
  }
}

🔧 测试

1. 单元测试

tsx
import { render, screen } from '@testing-library/react'
import Component from './Component'

test('renders component', () => {
  render(<Component />)
  expect(screen.getByText('Hello')).toBeInTheDocument()
})

2. E2E 测试

ts
import { test, expect } from '@playwright/test'

test('home page', async ({ page }) => {
  await page.goto('/')
  await expect(page.getByRole('heading')).toBeVisible()
})

🔗 相关资源


恭喜! 你已经完成了 Next.js 教程的学习。继续实践,构建出色的应用!