Skip to content

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>
  )
}

添加导航

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 main

2. 连接 Vercel

  1. 访问 vercel.com
  2. 导入 Git 仓库
  3. 配置项目设置
  4. 点击部署

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 应用的绝佳选择。

本站内容仅供学习和研究使用。