Skip to content

NextJs 基础 ​

概述 ​

Next.js 是一个基于 React 的全栈框架,提供了服务端渲染、静态站点生成、文件路由等能力。

核心特性 ​

  • 混合渲染 — 支持 CSR、SSR、SSG、ISR 四种渲染方式
  • 文件路由 — 基于文件系统的路由机制
  • 全栈能力 — 内置 API Routes,前后端一体开发
  • 自动优化 — 图片、字体、脚本自动优化
  • Server Actions — 无需手动创建接口,直接调用服务端函数

创建项目 ​

bash
# 默认 App Router(推荐)
npx create-next-app@latest my-app

# Pages Router
npx create-next-app@latest my-app --use-pages-router
# 默认 App Router(推荐)
npx create-next-app@latest my-app

# Pages Router
npx create-next-app@latest my-app --use-pages-router

创建过程中可选择 TypeScript、ESLint、Tailwind CSS、src/ 目录等选项。

目录结构 ​

my-app/
  src/
    app/              # App Router 目录
      layout.tsx      # 根布局(必须存在)
      page.tsx        # 首页
      globals.css     # 全局样式
    api/              # API Routes(可选)
  public/             # 静态资源
  next.config.mjs     # Next.js 配置
  package.json
  tsconfig.json
my-app/
  src/
    app/              # App Router 目录
      layout.tsx      # 根布局(必须存在)
      page.tsx        # 首页
      globals.css     # 全局样式
    api/              # API Routes(可选)
  public/             # 静态资源
  next.config.mjs     # Next.js 配置
  package.json
  tsconfig.json

App Router vs Pages Router ​

特性App RouterPages Router
引入版本Next.js 13.4+初始版本
路由方式文件路由(page.tsx)文件路由(index.tsx)
布局layout.tsx 嵌套布局无原生布局支持
数据获取服务端组件直接 async/awaitgetServerSideProps / getStaticProps
服务端组件默认支持不支持
API Routesroute.tsapi 目录下文件

配置 next.config.mjs ​

js
/** @type {import('next').NextConfig} */
const nextConfig = {
  logging: {
    fetches: {
      fullUrl: true  // 打印 fetch 缓存信息
    }
  },
  images: {
    domains: ['example.com'],  // 允许的外部图片域名
  }
}

export default nextConfig
/** @type {import('next').NextConfig} */
const nextConfig = {
  logging: {
    fetches: {
      fullUrl: true  // 打印 fetch 缓存信息
    }
  },
  images: {
    domains: ['example.com'],  // 允许的外部图片域名
  }
}

export default nextConfig

Metadata 与 SEO ​

tsx
// 静态 metadata
export const metadata = {
  title: 'My App',
  description: 'My App Description',
}

// 动态 metadata
export async function generateMetadata({ params }) {
  const post = await getPost(params.id)
  return {
    title: post.title,
    description: post.excerpt,
  }
}
// 静态 metadata
export const metadata = {
  title: 'My App',
  description: 'My App Description',
}

// 动态 metadata
export async function generateMetadata({ params }) {
  const post = await getPost(params.id)
  return {
    title: post.title,
    description: post.excerpt,
  }
}

App Router 核心约定文件 ​

文件名作用
page.tsx页面组件
layout.tsx布局(跨路由保持状态)
template.tsx模板(切换路由重新渲染)
loading.tsx加载状态(基于 Suspense)
error.tsx错误边界
not-found.tsx404 页面
route.tsAPI 路由处理程序

'use client' 指令 ​

'use client' 声明该模块在客户端执行。默认情况下 Next.js 组件是服务端组件:

tsx
'use client'
import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}
'use client'
import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

环境变量 ​

Next.js 内置对环境变量的支持:

bash
# .env.local(本地环境,优先级最高)
DATABASE_URL=mysql://localhost:3306/db
NEXT_PUBLIC_API_URL=https://api.example.com  # NEXT_PUBLIC_ 前缀暴露给客户端
# .env.local(本地环境,优先级最高)
DATABASE_URL=mysql://localhost:3306/db
NEXT_PUBLIC_API_URL=https://api.example.com  # NEXT_PUBLIC_ 前缀暴露给客户端
文件作用
.env.local本地环境,会覆盖其他配置
.env.development开发环境(next dev)
.env.production生产环境(next start)
.env所有环境默认值

注意:不带 NEXT_PUBLIC_ 前缀的变量仅在服务端可用,客户端代码中访问会返回 undefined。

next/image 图片优化 ​

Next.js 提供内置的 Image 组件,自动优化图片:

tsx
import Image from 'next/image'

// 本地图片
import avatar from './avatar.png'
<Image src={avatar} alt="avatar" />

// 远程图片(需在 next.config.mjs 配置域名)
<Image
  src="https://example.com/photo.jpg"
  alt="photo"
  width={800}
  height={600}
  priority  // 首屏图片优先加载
/>
import Image from 'next/image'

// 本地图片
import avatar from './avatar.png'
<Image src={avatar} alt="avatar" />

// 远程图片(需在 next.config.mjs 配置域名)
<Image
  src="https://example.com/photo.jpg"
  alt="photo"
  width={800}
  height={600}
  priority  // 首屏图片优先加载
/>

配置远程图片域名 ​

js
// next.config.mjs
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
      },
    ],
  },
}
// next.config.mjs
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
      },
    ],
  },
}

图片特性 ​

  • 自动优化 — 转换格式(WebP/AVIF),调整尺寸
  • 懒加载 — 默认懒加载,进入视口才加载
  • 防止 CLS — 需指定宽高或使用 fill 属性
  • 占位符 — placeholder="blur" 支持模糊占位

next/font 字体优化 ​

自动优化字体,消除外部请求:

tsx
import { Inter, Geist } from 'next/font/google'

// 自定义 CSS 变量
const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
})

const inter = Inter({ subsets: ['latin'] })

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${geistSans.variable}`}>
      <body className={inter.className}>{children}</body>
    </html>
  )
}
import { Inter, Geist } from 'next/font/google'

// 自定义 CSS 变量
const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
})

const inter = Inter({ subsets: ['latin'] })

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${geistSans.variable}`}>
      <body className={inter.className}>{children}</body>
    </html>
  )
}

优势:字体文件在构建时下载,与静态资源一起托管,无外部网络请求。

next/script 脚本加载 ​

tsx
import Script from 'next/script'

export default function Page() {
  return (
    <>
      <Script
        src="https://analytics.example.com/script.js"
        strategy="afterInteractive"  // 默认,页面可交互后加载
        // strategy="beforeInteractive"  // 在页面可交互前加载
        // strategy="lazyOnload"  // 浏览器空闲时加载
      />
    </>
  )
}
import Script from 'next/script'

export default function Page() {
  return (
    <>
      <Script
        src="https://analytics.example.com/script.js"
        strategy="afterInteractive"  // 默认,页面可交互后加载
        // strategy="beforeInteractive"  // 在页面可交互前加载
        // strategy="lazyOnload"  // 浏览器空闲时加载
      />
    </>
  )
}
strategy说明
beforeInteractive页面可交互前加载(关键脚本)
afterInteractive页面可交互后加载(默认,分析工具)
lazyOnload浏览器空闲时加载(低优先级)

常用命令 ​

bash
npm run dev       # 开发模式
npm run build     # 构建
npm start         # 启动生产服务
npm run lint      # 代码检查
npm run dev       # 开发模式
npm run build     # 构建
npm start         # 启动生产服务
npm run lint      # 代码检查