61 - Next.js 全栈框架教程

适用人群:有React基础
难度:中等
预计学习时间:30-40小时

为什么学 Next.js?

优势说明
React全栈前后端一体化,开发效率极高
SSR/SSG服务端渲染,SEO友好
生态最强Vercel维护,社区最活跃
部署简单Vercel一键部署
企业采用Netflix/TikTok/Notion都在用

学习路线

第1阶段:基础(1周)
├── 项目创建与结构
├── App Router(新路由系统)
├── 页面与布局(page.tsx/layout.tsx)
├── 客户端与服务端组件
└── 样式方案(CSS Modules/Tailwind)

第2阶段:数据获取(2周)
├── Server Components数据获取
├── Server Actions(表单处理)
├── API Routes
├── 数据库(Prisma + PostgreSQL)
└── 缓存策略(revalidate)

第3阶段:认证与中间件(1周)
├── NextAuth.js
├── Session管理
├── 中间件(middleware.ts)
└── 权限控制

第4阶段:高级特性(2周)
├── 图片优化(next/image)
├── 字体优化(next/font)
├── 国际化(i18n)
├── SEO优化(metadata)
├── 性能优化
└── 测试(Jest/Playwright)


核心代码示例

// app/layout.tsx - 根布局
export const metadata = {
  title: 'My App',
  description: 'Built with Next.js',
}

export default function RootLayout({ children }) {
  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  )
}

// app/page.tsx - 首页(服务端组件)
async function getPosts() {
  const res = await fetch('https://api.example.com/posts', {
    next: { revalidate: 60 }  // 每60秒重新验证
  })
  return res.json()
}

export default async function HomePage() {
  const posts = await getPosts()
  
  return (
    <main>
      <h1>Latest Posts</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.summary}</p>
        </article>
      ))}
    </main>
  )
}

// app/posts/[id]/page.tsx - 动态路由
export async function generateStaticParams() {
  const posts = await getPosts()
  return posts.map(post => ({ id: post.id }))
}

export default async function PostPage({ params }) {
  const post = await getPost(params.id)
  return <article>{post.content}</article>
}

// app/components/Counter.tsx - 客户端组件
'use client'
import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)
  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  )
}

// app/api/posts/route.ts - API路由
import { NextResponse } from 'next/server'

export async function GET() {
  const posts = await db.post.findMany()
  return NextResponse.json(posts)
}

export async function POST(request) {
  const body = await request.json()
  const post = await db.post.create({ data: body })
  return NextResponse.json(post, { status: 201 })
}

// Server Actions - 表单处理
// app/actions.ts
'use server'

export async function createPost(formData) {
  const title = formData.get('title')
  const content = formData.get('content')
  
  await db.post.create({
    data: { title, content }
  })
  
  revalidatePath('/posts')
}

// app/posts/new/page.tsx
import { createPost } from '../actions'

export default function NewPost() {
  return (
    <form action={createPost}>
      <input name="title" placeholder="标题" />
      <textarea name="content" placeholder="内容" />
      <button type="submit">发布</button>
    </form>
  )
}

// Prisma ORM
// prisma/schema.prisma
// generator client {
//   provider = "prisma-client-js"
// }
// 
// datasource db {
//   provider = "postgresql"
//   url      = env("DATABASE_URL")
// }
// 
// model Post {
//   id        String   @id @default(cuid())
//   title     String
//   content   String?
//   createdAt DateTime @default(now())
// }


部署方案

方案说明费用
Vercel官方推荐,一键部署免费/付费
Docker自建服务器部署服务器费用
AWS AmplifyAWS生态按量付费
NetlifyVercel替代免费/付费

推荐资源

资源说明
Next.js官方文档最好的学习资料
Next.js Learn官方互动教程
Vercel Blog最佳实践和新特性
Prisma文档数据库ORM
返回首页