Appearance
Next.js 开发指南
Next.js 是 React 的生产级框架,提供了服务端渲染、静态生成、路由等开箱即用的功能。本文将介绍 Next.js 的核心概念和开发实践。
Next.js 简介
Next.js 是 Vercel 开发的 React 框架,具有以下特性:
- 服务端渲染(SSR):提升首屏加载速度和 SEO
- 静态站点生成(SSG):预渲染页面,提升性能
- 自动代码分割:按页面自动分割代码
- 文件系统路由:基于文件系统的路由系统
- API Routes:内置 API 路由支持
项目初始化
创建项目
bash
npx create-next-app@latest my-app
cd my-app
npm run dev项目结构
my-app/
├── pages/ # 页面目录(路由)
│ ├── index.js # 首页 (/)
│ ├── about.js # 关于页 (/about)
│ └── api/ # API 路由
├── public/ # 静态资源
├── styles/ # 样式文件
└── components/ # 组件目录路由系统
文件系统路由
Next.js 使用文件系统作为路由系统:
javascript
// pages/index.js - 对应路由 /
export default function Home() {
return <h1>首页</h1>
}
// pages/about.js - 对应路由 /about
export default function About() {
return <h1>关于我们</h1>
}
// pages/blog/[id].js - 动态路由 /blog/123
export default function BlogPost({ id }) {
return <h1>文章 {id}</h1>
}动态路由
javascript
// pages/blog/[id].js
import { useRouter } from 'next/router'
export default function BlogPost() {
const router = useRouter()
const { id } = router.query
return <h1>文章 ID: {id}</h1>
}
// 多个动态参数
// pages/shop/[...slug].js - 捕获所有路由
// /shop/a -> { slug: ['a'] }
// /shop/a/b -> { slug: ['a', 'b'] }编程式导航
javascript
import Link from 'next/link'
import { useRouter } from 'next/router'
function Navigation() {
const router = useRouter()
return (
<nav>
{/* 使用 Link 组件 */}
<Link href="/about">
<a>关于</a>
</Link>
{/* 编程式导航 */}
<button onClick={() => router.push('/about')}>
跳转到关于页
</button>
</nav>
)
}数据获取
getStaticProps(静态生成)
在构建时获取数据,生成静态页面。
javascript
// pages/blog/[id].js
export default function BlogPost({ post }) {
return (
<article>
<h1>{post.title}</h1>
<div>{post.content}</div>
</article>
)
}
export async function getStaticProps({ params }) {
const post = await fetchPost(params.id)
return {
props: {
post
},
revalidate: 60 // ISR: 60秒后重新生成
}
}
export async function getStaticPaths() {
const posts = await fetchAllPosts()
const paths = posts.map(post => ({
params: { id: post.id.toString() }
}))
return {
paths,
fallback: false // 或 'blocking' 或 true
}
}getServerSideProps(服务端渲染)
每次请求时在服务端获取数据。
javascript
// pages/user/[id].js
export default function User({ user }) {
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
)
}
export async function getServerSideProps({ params }) {
const user = await fetchUser(params.id)
if (!user) {
return {
notFound: true
}
}
return {
props: {
user
}
}
}客户端数据获取
使用 useEffect 或 SWR/React Query 在客户端获取数据。
javascript
import { useState, useEffect } from 'react'
function UserProfile({ userId }) {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
setUser(data)
setLoading(false)
})
}, [userId])
if (loading) return <div>加载中...</div>
return <div>{user.name}</div>
}API Routes
Next.js 允许在 pages/api 目录下创建 API 路由。
javascript
// pages/api/users/[id].js
export default function handler(req, res) {
const { id } = req.query
if (req.method === 'GET') {
const user = getUserById(id)
res.status(200).json(user)
} else if (req.method === 'POST') {
const user = createUser(req.body)
res.status(201).json(user)
} else {
res.setHeader('Allow', ['GET', 'POST'])
res.status(405).end(`Method ${req.method} Not Allowed`)
}
}样式处理
CSS Modules
javascript
// styles/Button.module.css
.button {
padding: 10px 20px;
background: blue;
color: white;
}
// components/Button.js
import styles from '../styles/Button.module.css'
export default function Button() {
return <button className={styles.button}>按钮</button>
}全局样式
javascript
// styles/globals.css
body {
margin: 0;
font-family: sans-serif;
}
// pages/_app.js
import '../styles/globals.css'
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}Tailwind CSS
bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pjavascript
// tailwind.config.js
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
plugins: [],
}图片优化
Next.js 提供了优化的 Image 组件。
javascript
import Image from 'next/image'
function MyComponent() {
return (
<Image
src="/images/hero.jpg"
alt="Hero image"
width={800}
height={600}
priority // 优先加载
/>
)
}环境变量
javascript
// .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
SECRET_KEY=your-secret-key
// 使用
// 客户端可访问(NEXT_PUBLIC_ 前缀)
const apiUrl = process.env.NEXT_PUBLIC_API_URL
// 仅服务端可访问
const secretKey = process.env.SECRET_KEY部署
Vercel 部署(推荐)
bash
npm install -g vercel
vercel静态导出
javascript
// next.config.js
module.exports = {
output: 'export',
images: {
unoptimized: true
}
}bash
npm run build
# 生成 out/ 目录,可以部署到任何静态托管服务最佳实践
- 使用 TypeScript:提供类型安全
- 代码分割:利用 Next.js 的自动代码分割
- 图片优化:使用 Next.js Image 组件
- SEO 优化:使用 Head 组件设置 meta 标签
- 性能监控:使用 Web Vitals 监控性能
总结
Next.js 为 React 应用提供了完整的解决方案,包括路由、数据获取、样式处理等。通过合理使用 Next.js 的特性,可以构建高性能、SEO 友好的 React 应用。掌握 Next.js 是现代 React 开发的重要技能。