Next.js 入门指南

Next.js 已经成为 React 生态系统中最受欢迎的框架之一,它简化了 React 应用的开发流程,提供了开箱即用的解决方案。

什么是 Next.js?

Next.js 是一个基于 React 的生产级全栈框架,由 Vercel 公司开发维护。它提供了许多强大功能:

  • 服务端渲染(SSR) - 更好的 SEO 和初始加载性能
  • 静态站点生成(SSG) - 超快的页面加载速度
  • API 路由 - 轻松创建后端 API
  • 自动代码分割 - 优化打包大小
  • 零配置 - 开箱即用的优化配置
  • TypeScript 支持 - 完整的类型支持
  • 快速刷新 - 极佳的开发体验

环境准备

在开始之前,确保你的系统已安装:

  • Node.js 16.8 或更高版本
  • npm、yarn 或 pnpm 包管理器

创建第一个 Next.js 项目

方法一:使用 create-next-app(推荐)

bash 复制代码
npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm run dev

创建过程中,CLI 会询问一些配置选项:

  • 是否使用 TypeScript?(推荐选择是)
  • 是否使用 ESLint?(推荐选择是)
  • 是否使用 Tailwind CSS?(根据喜好选择)
  • 是否使用 src/ 目录?(可选)
  • 是否使用 App Router?(新项目推荐选择是)
  • 是否自定义导入别名?(通常选择否)

方法二:手动设置

如果你喜欢从零开始配置:

bash 复制代码
mkdir my-nextjs-app
cd my-nextjs-app
npm init -y
npm install next react react-dom

package.json 中添加脚本:

json 复制代码
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
}

创建必要的目录结构:

bash 复制代码
mkdir app pages public

Next.js 版本对比与演进

Next.js 主要版本特性对比

特性维度 v12 (Pages Router) v13 (过渡版) v14+ (App Router稳定版) 说明
路由系统 pages/目录 文件即路由 pages/和 app/共存 app/目录 全面转向 App Router 最大的架构变革
数据获取 getStaticProps getServerSideProps 支持 async组件 (试验性) 直接 async组件 服务端获取数据 更直观,代码更少
组件类型 全是客户端组件 引入 服务端组件 (需配置) 服务端组件为默认 客户端需 'use client' 混合渲染,性能优化
布局系统 手动包装布局 (如 ) 支持 layout.js (试验性) 文件级布局 layout.js自动嵌套 布局共享更简单
API 路由 pages/api/目录 pages/api/ 和 app/api/共存 app/api/route.js 基于 HTTP 方法 (GET, POST) 更符合 REST 规范
元数据管理 手动在 中写 部分支持 metadata 完整 的 metadataAPI 支持 SEO和社交卡片 静态SEO优化更方便
渲染模式 SSG, SSR, CSR 支持流式渲染 (Streaming) + Suspense 流式渲染稳定 部分 HTML 先输出 提升首屏加载速度

Pages Router vs App Router 详细对比

Pages Router(传统方式)

项目结构:

复制代码
pages/
├── index.js          # / 路由
├── about.js          # /about 路由
├── blog/
│   ├── index.js      # /blog 路由
│   └── [id].js       # /blog/1 动态路由
└── api/
    └── users.js      # /api/users API 路由

特点:

  • 基于文件系统的路由
  • 使用 getServerSidePropsgetStaticProps 进行数据获取
  • 相对成熟稳定,社区资源丰富

示例代码:

jsx 复制代码
// pages/index.js
export default function Home({ posts }) {
  return (
    <div>
      <h1>首页</h1>
      {posts.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  )
}

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()
  
  return {
    props: { posts }
  }
}

App Router(新方式,Next.js 13+)

项目结构:

复制代码
app/
├── layout.js         # 根布局
├── page.js           # / 路由
├── about/
│   └── page.js       # /about 路由
├── blog/
│   ├── page.js       # /blog 路由
│   └── [id]/
│       └── page.js   # /blog/1 动态路由
└── api/
    └── users/
        └── route.js  # /api/users API 路由

特点:

  • 基于 React Server Components
  • 使用 async/await 进行服务端数据获取
  • 支持嵌套布局和加载状态
  • 更好的性能优化

示例代码:

jsx 复制代码
// app/page.js
async function getPosts() {
  const res = await fetch('https://api.example.com/posts')
  return res.json()
}

export default async function Home() {
  const posts = await getPosts()
  
  return (
    <div>
      <h1>首页</h1>
      {posts.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  )
}

为什么推荐使用 App Router?

  1. 更好的性能:默认使用 React Server Components
  2. 更简单的数据获取:直接使用 async/await
  3. 改进的布局系统:嵌套布局支持
  4. 更好的加载状态:内置 loading.js 文件
  5. 未来导向:React 团队推荐的方向

Next.js 如何优化 SEO

1. 服务端渲染(SSR)

传统 React SPA 的问题:

html 复制代码
<!-- 初始 HTML -->
<div id="root"></div>
<!-- 需要 JavaScript 执行后才能看到内容 -->

Next.js SSR 的优势:

html 复制代码
<!-- 服务端直接返回完整 HTML -->
<div>
  <h1>我的博客</h1>
  <article>完整的文章内容...</article>
</div>

搜索引擎优化效果:

  • 爬虫可以直接看到完整内容
  • 不需要等待 JavaScript 执行
  • 更好的内容索引

2. 静态站点生成(SSG)

构建时生成静态 HTML:

jsx 复制代码
// pages/posts/[id].js (Pages Router)
export async function getStaticPaths() {
  // 构建时获取所有可能的路径
  const posts = await getPosts()
  const paths = posts.map(post => ({
    params: { id: post.id.toString() }
  }))
  
  return { paths, fallback: false }
}

export async function getStaticProps({ params }) {
  // 构建时生成静态页面
  const post = await getPost(params.id)
  return { props: { post } }
}

SEO 优势:

  • 极快的加载速度(直接返回 HTML)
  • 更好的 Core Web Vitals 分数
  • 搜索引擎更喜欢快速加载的页面

3. 元数据优化

Pages Router 方式:

jsx 复制代码
// pages/index.js
import Head from 'next/head'

export default function Home() {
  return (
    <>
      <Head>
        <title>我的网站 - 最佳 React 框架</title>
        <meta name="description" content="Next.js 是React的最佳框架..." />
        <meta name="keywords" content="nextjs, react, ssr, seo" />
      </Head>
      <main>内容</main>
    </>
  )
}

App Router 方式(更简洁):

jsx 复制代码
// app/page.js
export const metadata = {
  title: '我的网站 - 最佳 React 框架',
  description: 'Next.js 是React的最佳框架...',
  keywords: 'nextjs, react, ssr, seo',
}

export default function Home() {
  return <main>内容</main>
}

4. 语义化 URL 和路由

动态路由优化:

jsx 复制代码
// app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)
  
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.image],
    },
  }
}

5. 图片优化和懒加载

jsx 复制代码
import Image from 'next/image'

export default function OptimizedImage() {
  return (
    <Image
      src="/hero.jpg"
      alt="描述性文字,有利于SEO"
      width={800}
      height={400}
      priority={true} // 关键图片优先加载
      placeholder="blur" // 模糊占位符
    />
  )
}

项目结构深度解析

App Router 完整项目结构

复制代码
my-nextjs-app/
├── app/                    # App Router 目录
│   ├── globals.css         # 全局样式
│   ├── layout.js          # 根布局组件
│   ├── page.js            # 首页组件
│   ├── loading.js         # 加载状态组件
│   ├── error.js           # 错误边界组件
│   ├── not-found.js       # 404 页面
│   ├── about/
│   │   └── page.js        # /about 页面
│   ├── blog/
│   │   ├── page.js        # /blog 列表页
│   │   ├── loading.js     # 博客页面的加载状态
│   │   └── [slug]/
│   │       └── page.js    # /blog/xxx 详情页
│   └── api/
│       └── posts/
│           └── route.js   # API 路由
├── components/             # 可复用组件
│   ├── ui/                # UI 基础组件
│   └── layout/            # 布局组件
├── lib/                   # 工具函数库
├── public/                # 静态资源
└── next.config.js        # Next.js 配置

数据获取深度解析

服务端数据获取模式

1. 静态生成(推荐用于内容型网站)

jsx 复制代码
// 构建时生成,适合不经常变化的内容
async function getStaticData() {
  const res = await fetch('https://api.example.com/posts')
  return res.json()
}

2. 服务端渲染(推荐用于动态内容)

jsx 复制代码
// 每次请求时生成,适合实时数据
async function getServerData() {
  const res = await fetch('https://api.example.com/posts', {
    cache: 'no-store' // 禁止缓存
  })
  return res.json()
}

3. 增量静态再生(ISR)

jsx 复制代码
// 静态生成,但定期更新
async function getISRData() {
  const res = await fetch('https://api.example.com/posts', {
    next: { revalidate: 60 } // 60秒后重新验证
  })
  return res.json()
}

客户端数据获取最佳实践

jsx 复制代码
'use client'

import { useState, useEffect } from 'react'
import { useSWR } from 'swr'

export default function ClientComponent() {
  const { data, error, isLoading } = useSWR(
    '/api/posts',
    fetcher,
    {
      revalidateOnFocus: false,
      dedupingInterval: 60000
    }
  )
  
  if (error) return <div>加载失败</div>
  if (isLoading) return <div>加载中...</div>
  
  return (
    <div>
      {data.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  )
}

高级特性与优化

1. 中间件(Middleware)

jsx 复制代码
// middleware.js
import { NextResponse } from 'next/server'

export function middleware(request) {
  // 身份验证检查
  if (!request.cookies.get('token')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
  
  return NextResponse.next()
}

export const config = {
  matcher: '/admin/:path*'
}

2. 国际化(i18n)

javascript 复制代码
// next.config.js
module.exports = {
  i18n: {
    locales: ['zh-CN', 'en-US'],
    defaultLocale: 'zh-CN',
  },
}

3. 环境变量配置

javascript 复制代码
// .env.local
DATABASE_URL=your_database_url
NEXT_PUBLIC_API_URL=https://api.example.com

// next.config.js
module.exports = {
  env: {
    CUSTOM_KEY: process.env.CUSTOM_KEY,
  },
}

部署与生产优化

构建优化配置

javascript 复制代码
// next.config.js
module.exports = {
  experimental: {
    optimizeCss: true,
  },
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production',
  },
  images: {
    domains: ['example.com'],
    formats: ['image/webp', 'image/avif'],
  },
}

性能监控

javascript 复制代码
// app/layout.js
import { Analytics } from '@vercel/analytics/react'

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

常见问题解决方案

1. 白屏问题

  • 检查组件是否正确导出为默认导出
  • 确认文件路径和命名符合 Next.js 规范
  • 查看浏览器控制台错误信息

2. 样式不生效

  • 确认 CSS 文件正确导入
  • 检查类名拼写和样式优先级
  • 使用开发者工具检查样式应用

3. 构建失败

  • 检查 Node.js 版本是否符合要求
  • 确认所有依赖正确安装
  • 查看构建日志中的具体错误信息
相关推荐
wjs20243 小时前
《Foundation 滑块:界面设计的艺术与科学》
开发语言
罚时大师月色3 小时前
Vue+ts 如何实现父组件和子组件通信
javascript·vue.js·ecmascript
漂流瓶jz3 小时前
快速定位源码问题:SourceMap的生成/使用/文件格式与历史
前端·javascript·前端工程化
William_cl3 小时前
【C# OOP 入门到精通】从基础概念到 MVC 实战(含 SOLID 原则与完整代码)
开发语言·c#·mvc
fury_1233 小时前
vue3:数组的.includes方法怎么使用
前端·javascript·vue.js
宁&沉沦4 小时前
Cursor 科技感的登录页面提示词
前端·javascript·vue.js
Dragonir4 小时前
React+Three.js 实现 Apple 2025 热成像 logo
前端·javascript·html·three.js·页面特效
少许极端4 小时前
算法奇妙屋(七)-字符串操作
java·开发语言·数据结构·算法·字符串操作
懒羊羊不懒@4 小时前
Java基础语法—字面量、变量详解、存储数据原理
java·开发语言