Next.js 快速上手
本章将带你快速创建第一个 Next.js 应用,了解基本概念和开发流程。
创建第一个 Next.js 应用
使用 create-next-app
最简单的方式是使用官方脚手架工具:
bash
# 使用 npm
npx create-next-app@latest my-next-app
# 使用 yarn
yarn create next-app my-next-app
# 使用 pnpm
pnpm create next-app my-next-app交互式创建
运行命令后会有交互式选项:
bash
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes启动开发服务器
bash
cd my-next-app
npm run dev访问 http://localhost:3000 查看应用。
项目结构概览
my-next-app/
├── app/ # App Router (Next.js 13+)
│ ├── globals.css # 全局样式
│ ├── layout.tsx # 根布局
│ └── page.tsx # 首页
├── public/ # 静态资源
├── next.config.js # Next.js 配置
├── package.json # 项目依赖
└── tailwind.config.js # Tailwind 配置创建第一个页面
App Router 方式 (推荐)
在 app 目录下创建页面:
typescript
// app/about/page.tsx
export default function About() {
return (
<div>
<h1>关于我们</h1>
<p>这是关于页面</p>
</div>
)
}Pages Router 方式
在 pages 目录下创建页面:
typescript
// pages/about.tsx
export default function About() {
return (
<div>
<h1>关于我们</h1>
<p>这是关于页面</p>
</div>
)
}添加样式
全局样式
css
/* app/globals.css */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
margin: 0;
padding: 20px;
}
h1 {
color: #333;
}CSS Modules
css
/* components/Button.module.css */
.button {
background-color: #0070f3;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
}
.button:hover {
background-color: #0051cc;
}typescript
// components/Button.tsx
import styles from './Button.module.css'
export default function Button({ children }: { children: React.ReactNode }) {
return (
<button className={styles.button}>
{children}
</button>
)
}创建组件
简单组件
typescript
// components/Header.tsx
export default function Header() {
return (
<header>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
</nav>
</header>
)
}使用组件
typescript
// app/layout.tsx
import Header from '@/components/Header'
import './globals.css'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="zh">
<body>
<Header />
<main>{children}</main>
</body>
</html>
)
}添加导航
使用 Link 组件
typescript
// components/Navigation.tsx
import Link from 'next/link'
export default function Navigation() {
return (
<nav>
<Link href="/">首页</Link>
<Link href="/about">关于</Link>
<Link href="/contact">联系</Link>
</nav>
)
}导航样式
css
/* components/Navigation.module.css */
.nav {
display: flex;
gap: 20px;
padding: 20px 0;
}
.link {
text-decoration: none;
color: #0070f3;
font-weight: 500;
}
.link:hover {
text-decoration: underline;
}处理静态资源
图片
typescript
// app/page.tsx
import Image from 'next/image'
export default function Home() {
return (
<div>
<h1>欢迎使用 Next.js</h1>
<Image
src="/logo.png"
alt="Logo"
width={200}
height={100}
/>
</div>
)
}公共文件
将文件放在 public 目录下:
public/
├── favicon.ico
├── logo.png
└── images/
└── hero.jpg环境变量
创建环境文件
bash
# .env.local
DATABASE_URL=your_database_url
API_KEY=your_api_key
NEXT_PUBLIC_API_URL=https://api.example.com使用环境变量
typescript
// 服务端使用
const dbUrl = process.env.DATABASE_URL
// 客户端使用 (需要 NEXT_PUBLIC_ 前缀)
const apiUrl = process.env.NEXT_PUBLIC_API_URL基本数据获取
服务端组件 (App Router)
typescript
// app/posts/page.tsx
async function getPosts() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts')
return res.json()
}
export default async function Posts() {
const posts = await getPosts()
return (
<div>
<h1>文章列表</h1>
{posts.map((post: any) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</article>
))}
</div>
)
}客户端数据获取
typescript
'use client'
import { useState, useEffect } from 'react'
export default function ClientPosts() {
const [posts, setPosts] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
setPosts(data)
setLoading(false)
})
}, [])
if (loading) return <div>加载中...</div>
return (
<div>
<h1>文章列表</h1>
{posts.map((post: any) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</article>
))}
</div>
)
}部署到 Vercel
1. 推送到 Git
bash
git init
git add .
git commit -m "Initial commit"
git remote add origin your-repo-url
git push -u origin main2. 连接 Vercel
- 访问 vercel.com
- 导入 Git 仓库
- 配置项目设置
- 点击部署
3. 自动部署
每次推送到主分支都会自动部署。
常用命令
bash
# 开发模式
npm run dev
# 构建生产版本
npm run build
# 启动生产服务器
npm run start
# 代码检查
npm run lint
# 类型检查 (TypeScript)
npx tsc --noEmit开发技巧
1. 热重载
Next.js 支持热重载,修改代码后自动刷新页面。
2. 错误页面
typescript
// app/error.tsx
'use client'
export default function Error({
error,
reset,
}: {
error: Error
reset: () => void
}) {
return (
<div>
<h2>出错了!</h2>
<button onClick={() => reset()}>重试</button>
</div>
)
}3. 加载页面
typescript
// app/loading.tsx
export default function Loading() {
return <div>加载中...</div>
}4. 404 页面
typescript
// app/not-found.tsx
export default function NotFound() {
return (
<div>
<h2>页面未找到</h2>
<p>请检查 URL 是否正确</p>
</div>
)
}下一步
现在你已经创建了第一个 Next.js 应用!接下来可以学习:
总结
通过本章学习,你应该能够:
- 创建 Next.js 项目
- 理解基本项目结构
- 创建页面和组件
- 添加样式和导航
- 处理静态资源
- 进行基本的数据获取
- 部署应用到 Vercel
Next.js 提供了强大的功能和优秀的开发体验,是构建现代 React 应用的绝佳选择。