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(推荐)
npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm run dev
创建过程中,CLI 会询问一些配置选项:
- 是否使用 TypeScript?(推荐选择是)
- 是否使用 ESLint?(推荐选择是)
- 是否使用 Tailwind CSS?(根据喜好选择)
- 是否使用
src/
目录?(可选) - 是否使用 App Router?(新项目推荐选择是)
- 是否自定义导入别名?(通常选择否)
方法二:手动设置
如果你喜欢从零开始配置:
mkdir my-nextjs-app
cd my-nextjs-app
npm init -y
npm install next react react-dom
在 package.json
中添加脚本:
{"scripts": {"dev": "next dev","build": "next build","start": "next start","lint": "next lint"}
}
创建必要的目录结构:
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 路由
特点:
- 基于文件系统的路由
- 使用
getServerSideProps
、getStaticProps
进行数据获取 - 相对成熟稳定,社区资源丰富
示例代码:
// 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 进行服务端数据获取
- 支持嵌套布局和加载状态
- 更好的性能优化
示例代码:
// 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?
- 更好的性能:默认使用 React Server Components
- 更简单的数据获取:直接使用 async/await
- 改进的布局系统:嵌套布局支持
- 更好的加载状态:内置 loading.js 文件
- 未来导向:React 团队推荐的方向
Next.js 如何优化 SEO
1. 服务端渲染(SSR)
传统 React SPA 的问题:
<!-- 初始 HTML -->
<div id="root"></div>
<!-- 需要 JavaScript 执行后才能看到内容 -->
Next.js SSR 的优势:
<!-- 服务端直接返回完整 HTML -->
<div><h1>我的博客</h1><article>完整的文章内容...</article>
</div>
搜索引擎优化效果:
- 爬虫可以直接看到完整内容
- 不需要等待 JavaScript 执行
- 更好的内容索引
2. 静态站点生成(SSG)
构建时生成静态 HTML:
// 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 方式:
// 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 方式(更简洁):
// 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 和路由
动态路由优化:
// 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. 图片优化和懒加载
import Image from 'next/image'export default function OptimizedImage() {return (<Imagesrc="/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. 静态生成(推荐用于内容型网站)
// 构建时生成,适合不经常变化的内容
async function getStaticData() {const res = await fetch('https://api.example.com/posts')return res.json()
}
2. 服务端渲染(推荐用于动态内容)
// 每次请求时生成,适合实时数据
async function getServerData() {const res = await fetch('https://api.example.com/posts', {cache: 'no-store' // 禁止缓存})return res.json()
}
3. 增量静态再生(ISR)
// 静态生成,但定期更新
async function getISRData() {const res = await fetch('https://api.example.com/posts', {next: { revalidate: 60 } // 60秒后重新验证})return res.json()
}
客户端数据获取最佳实践
'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)
// 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)
// next.config.js
module.exports = {i18n: {locales: ['zh-CN', 'en-US'],defaultLocale: 'zh-CN',},
}
3. 环境变量配置
// .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,},
}
部署与生产优化
构建优化配置
// next.config.js
module.exports = {experimental: {optimizeCss: true,},compiler: {removeConsole: process.env.NODE_ENV === 'production',},images: {domains: ['example.com'],formats: ['image/webp', 'image/avif'],},
}
性能监控
// 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 版本是否符合要求
- 确认所有依赖正确安装
- 查看构建日志中的具体错误信息