Next.js 14 入门指南:从零开始构建现代 Web 应用

By Vincent Arak技术
6 min read

Next.js 14 入门指南:从零开始构建现代 Web 应用

Next.js 14 带来了许多激动人心的新特性,让 React 开发变得更加高效和愉快。在这篇文章中,我将带你了解 Next.js 14 的核心概念和最佳实践。

什么是 Next.js?

Next.js 是一个基于 React 的全栈框架,它提供了:

  • 服务端渲染 (SSR) - 更好的 SEO 和首屏加载速度
  • 静态站点生成 (SSG) - 极快的页面加载速度
  • API 路由 - 全栈开发能力
  • 自动代码分割 - 优化的性能
  • 内置优化 - 图片、字体等资源优化

Next.js 14 的新特性

1. 稳定的 App Router

App Router 现在已经稳定,提供了更直观的路由系统:

// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
  return <h1>文章: {params.slug}</h1>
}

// 生成静态参数
export async function generateStaticParams() {
  const posts = await getPosts()
  return posts.map((post) => ({
    slug: post.slug,
  }))
}

2. Server Components

Server Components 让你可以在服务端渲染组件:

// 这个组件在服务端运行
async function ServerComponent() {
  const data = await fetch('https://api.example.com/data')
  const posts = await data.json()
  
  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  )
}

3. 改进的图片优化

新的 Image 组件提供了更好的性能:

import Image from 'next/image'

function MyComponent() {
  return (
    <Image
      src="/hero.jpg"
      alt="Hero image"
      width={800}
      height={400}
      priority // 首屏图片优先加载
      placeholder="blur" // 模糊占位符
    />
  )
}

创建你的第一个 Next.js 应用

1. 安装和设置

# 创建新项目
npx create-next-app@latest my-blog --typescript --tailwind --app

# 进入项目目录
cd my-blog

# 启动开发服务器
npm run dev

2. 项目结构

my-blog/
├── app/                 # App Router 目录
│   ├── globals.css     # 全局样式
│   ├── layout.tsx      # 根布局
│   ├── page.tsx        # 首页
│   └── blog/           # 博客路由
├── components/         # React 组件
├── lib/               # 工具函数
├── public/            # 静态资源
└── next.config.js     # Next.js 配置

3. 创建布局组件

// app/layout.tsx
import './globals.css'

export const metadata = {
  title: '我的博客',
  description: '分享技术和生活',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN">
      <body>
        <header>
          <nav>
            <a href="/">首页</a>
            <a href="/blog">博客</a>
            <a href="/about">关于</a>
          </nav>
        </header>
        <main>{children}</main>
        <footer>
          <p>&copy; 2024 我的博客</p>
        </footer>
      </body>
    </html>
  )
}

数据获取策略

1. 服务端数据获取

// app/blog/page.tsx
async function getBlogPosts() {
  const res = await fetch('https://api.example.com/posts', {
    cache: 'force-cache', // 静态生成
  })
  return res.json()
}

export default async function BlogPage() {
  const posts = await getBlogPosts()
  
  return (
    <div>
      <h1>博客文章</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  )
}

2. 客户端数据获取

'use client' // 客户端组件

import { useState, useEffect } from 'react'

export default function ClientComponent() {
  const [data, setData] = useState(null)
  
  useEffect(() => {
    fetch('/api/data')
      .then(res => res.json())
      .then(setData)
  }, [])
  
  if (!data) return <div>加载中...</div>
  
  return <div>{/* 渲染数据 */}</div>
}

性能优化技巧

1. 代码分割

import dynamic from 'next/dynamic'

// 动态导入组件
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <p>加载中...</p>,
})

export default function Page() {
  return (
    <div>
      <h1>我的页面</h1>
      <HeavyComponent />
    </div>
  )
}

2. 缓存策略

// 静态生成,永久缓存
fetch(url, { cache: 'force-cache' })

// 每次请求都重新获取
fetch(url, { cache: 'no-store' })

// 定时重新验证
fetch(url, { next: { revalidate: 3600 } }) // 1小时

3. 流式渲染

import { Suspense } from 'react'

export default function Page() {
  return (
    <div>
      <h1>我的页面</h1>
      <Suspense fallback={<div>加载中...</div>}>
        <SlowComponent />
      </Suspense>
    </div>
  )
}

API 路由

1. 创建 API 端点

// app/api/posts/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams
  const query = searchParams.get('q')
  
  // 获取数据逻辑
  const posts = await getPosts(query)
  
  return NextResponse.json({ posts })
}

export async function POST(request: NextRequest) {
  const body = await request.json()
  
  // 创建文章逻辑
  const newPost = await createPost(body)
  
  return NextResponse.json({ post: newPost }, { status: 201 })
}

2. 动态路由

// app/api/posts/[id]/route.ts
export async function GET(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  const post = await getPost(params.id)
  
  if (!post) {
    return NextResponse.json({ error: '文章未找到' }, { status: 404 })
  }
  
  return NextResponse.json({ post })
}

部署到生产环境

1. 构建应用

# 构建生产版本
npm run build

# 启动生产服务器
npm start

2. 部署到 Vercel

# 安装 Vercel CLI
npm i -g vercel

# 部署
vercel

# 部署到生产环境
vercel --prod

3. 环境变量

# .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgresql://...

最佳实践

1. 组件组织

components/
├── ui/              # 基础 UI 组件
│   ├── Button.tsx
│   └── Input.tsx
├── layout/          # 布局组件
│   ├── Header.tsx
│   └── Footer.tsx
└── features/        # 功能组件
    ├── blog/
    └── auth/

2. 类型安全

// types/blog.ts
export interface BlogPost {
  id: string
  title: string
  content: string
  publishedAt: Date
  author: {
    name: string
    avatar: string
  }
}

// 使用类型
function BlogPostCard({ post }: { post: BlogPost }) {
  return (
    <article>
      <h2>{post.title}</h2>
      <p>作者:{post.author.name}</p>
    </article>
  )
}

3. 错误处理

// app/error.tsx
'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <h2>出错了!</h2>
      <p>{error.message}</p>
      <button onClick={reset}>重试</button>
    </div>
  )
}

总结

Next.js 14 为现代 Web 开发提供了强大的工具和优化。通过合理使用 Server Components、App Router 和内置优化功能,你可以构建出性能卓越的 Web 应用。

关键要点

  • App Router 提供了更直观的路由系统
  • Server Components 让服务端渲染更加高效
  • 内置优化 确保最佳性能
  • 类型安全 通过 TypeScript 提高开发体验

下一步

  • 尝试构建一个简单的博客应用
  • 探索 Next.js 的高级功能
  • 学习性能优化技巧
  • 部署你的第一个 Next.js 应用

希望这篇指南能帮助你开始 Next.js 14 的学习之旅!如果你有任何问题,欢迎在评论区留言讨论。


想了解更多 Next.js 内容?订阅我的博客获取最新文章更新!