Next.js 介绍

介绍了 Next.js 的基本概念和实现原理,以及在 React 中的应用。

一、Next.js 是什么?

  • 定位:基于 React 的全栈 Web 框架,用来构建从简单博客到复杂 SaaS 的各种 Web 应用。

  • 作者&公司:由 Vercel 公司及社区维护,最初由 Guillermo Rauch 等人创建。(维基百科)

  • 首次发布:2016 年 10 月 25 日开源。(维基百科)

  • 语言与运行环境

    • 前端用 JavaScript / TypeScript + React
    • 后端基于 Node.js / Edge Runtime
    • 内部还使用 Rust 实现编译与打包工具(Turbopack 等)(维基百科)
  • 协议:MIT 开源许可。(维基百科)

简单说:Next.js 在 React 基础上,帮你解决了路由、数据获取、渲染模式、SEO、静态导出、代码拆分、图片和字体优化、API 层等一整套问题,是一个“拿来就能上生产”的应用框架。

二、为什么要用 Next.js(核心特性总览)

1. 文件系统路由(File-based Routing)

  • 按照文件夹结构自动生成路由:

    • app/pages/ 目录下创建文件就等于创建页面。
  • 支持:

    • 动态路由:[id].tsx
    • 嵌套路由:子目录结构
    • 捕获所有路由:[...slug].tsx

你不需要再手写路由表,结构一目了然。(Next.js)

2. 多种渲染模式:SSR / SSG / ISR / CSR

Next.js 最大的卖点之一就是灵活的渲染策略,可以按页面设置:

  • SSR(Server-Side Rendering)服务器端渲染
    每次请求时在服务端生成 HTML,适合实时数据+良好 SEO 的页面。
  • SSG(Static Site Generation)静态生成
    构建时把页面生成为静态 HTML,适合内容相对稳定的页面(博客、文档)。
  • ISR(Incremental Static Regeneration)增量静态再生成
    结合 SSG + 定时再生,页面第一次生成后,被访问一段时间后自动后台重建,做到 “静态性能 + 动态更新”。(strapi.io)
  • CSR(Client-Side Rendering)客户端渲染
    通过纯 React 组件在浏览器侧渲染,适合高度交互的 SPA 部分。

这让你可以在同一个项目里,对不同页面选择不同策略:例如首页 SSG+ISR,后台管理页面用 SSR 或 CSR。

3. App Router 与 Pages Router

当前 Next.js 支持两套路由系统:(Next.js)

  • Pages Router(旧)

    • 使用 pages/ 目录
    • 一直沿用到 Next.js 12 时代的经典模式
    • SSR / SSG / ISR API 为 getServerSideProps, getStaticProps
  • App Router(新)

    • 使用 app/ 目录(推荐新项目使用)

    • 核心特点:

      • React Server Components(服务器组件)
      • 嵌套布局(layouts)与并行路由
      • Streaming(流式渲染)
      • 更精细的数据获取与缓存控制
      • 更自然的全栈模式(Route Handlers,Server Actions 等)

你可以理解为:App Router 是为 React 18/19 新特性重新设计的一套 Next.js 架构

4. React Server Components(RSC)

  • 在 App Router 中,页面和布局默认是 Server Components

    • 在服务器运行,直接访问数据库或后端服务
    • 渲染结果是 HTML 片段,减少发送到浏览器的 JS 体积
    • 不参与客户端状态、事件处理(因此更轻更快)(Next.js)
  • 当需要交互(比如按钮点击、表单输入、动画)时:

    • 在组件文件顶部加上 "use client" 声明,把该组件设为 Client Component,在浏览器执行。

这种模式可以细粒度地控制“哪些逻辑必须在浏览器跑,哪些可以放在后端”,对性能和开发体验非常有利。

5. 全栈能力:API Routes / Route Handlers / Server Actions

Next.js 不是只负责前端页面,它本身就是一个全栈框架

  • API Routes(Pages Router):在 pages/api/*.ts 文件中定义 API 接口。

  • Route Handlers(App Router)

    • app/route.ts[route]/route.ts 里定义 GET, POST 等 HTTP 方法处理。(Next.js)
  • Server Actions

    • 使用 async function action() 'use server' { ... } 形式,把后端操作嵌入组件逻辑中,简化“前端调用后端”的样板代码。(raftlabs.com)

结果就是:你可以在一个 Next.js 项目里同时完成前端页面 + 后端接口 + 数据操作,非常适合中小团队和独立开发者。

6. 性能优化内建:图片、字体、代码拆分等

  • 图片优化next/image 组件自动:

    • 按设备尺寸和 DPR 生成合适尺寸
    • 使用现代格式(如 WebP)
    • 懒加载和占位图等。(Next.js)
  • 字体优化next/font 自动子集化、内联关键字体,减少 FOUT/FOIT。

  • 自动代码拆分(Code Splitting)

    • 按路由拆分 Bundle,避免一次性加载整个应用。(strapi.io)
  • Turbopack / Rust 编译管线

    • 新版本 Next.js 引入 Rust 写的打包器 Turbopack,相比 Webpack 有更快的冷启动和增量构建。(维基百科)

这些特性配合 SSR/SSG/ISR,可以显著提升 首屏速度、SEO 和 Lighthouse 指标

7. 中间件与 Edge Runtime

  • Middleware

    • 在请求进入路由之前,在边缘节点执行:做重定向、AB 测试、国际化、权限验证等逻辑。(raftlabs.com)
  • Edge Runtime

    • 运行在边缘计算环境(比如 Vercel Edge Functions),延迟更低,适合用户地理分布广的应用。

三、App Router 核心概念拆解

假设你使用推荐的新模式,即 app/ 目录,这些是你会高频接触的概念。(Next.js)

1. 项目结构

典型结构示例:

app/
  layout.tsx       // 根布局
  page.tsx         // 根页面 (/)
  blog/
    layout.tsx     // blog 区域布局
    page.tsx       // /blog
    [slug]/
      page.tsx     // /blog/:slug
  api/
    route.ts       // /api
public/
  ...静态资源
  • page.tsx:一个路由的页面组件
  • layout.tsx:包裹子路由的通用布局(头部、导航、底部)
  • loading.tsx:该路由的加载状态组件(配合 Suspense 与 Streaming)
  • error.tsx:错误边界
  • route.ts:定义路由处理(GET/POST 等)

2. 数据获取与渲染

在 App Router 里,数据获取官方推荐直接用 async Server Components

// app/blog/[slug]/page.tsx
import { getPost } from '@/lib/posts';

export default async function PostPage({ params }) {
  const post = await getPost(params.slug); // 这里直接访问数据库或 API

  return (
    <article>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.html }} />
    </article>
  );
}
  • 该组件只在服务器执行,不会打包到浏览器。
  • Next.js 会自动处理缓存与 streaming(视配置而定)。

你还可以通过:

  • 缓存 & 再验证:使用 fetchnext: { revalidate: 秒数 }revalidatePath 等 API 做 ISR 风格的再生成。(Next.js)
  • Route Handlers:在 app/api/posts/route.ts 定义 GET / POST 来服务数据。

3. Server / Client Components 的边界

  • 默认:所有 page.tsx, layout.tsx 都是 Server Components

  • 当你写组件需要:

    • useState, useEffect, useRef 等 Hook
    • 访问 window, document, localStorage
    • 处理点击、输入、拖拽等交互事件
    • 使用只支持浏览器的第三方 UI 组件库
      时,就需要在文件顶部写:
"use client";

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(c => c + 1)}>
      count: {count}
    </button>
  );
}
  • 这个组件会打包到浏览器,在客户端执行。
  • 可以把 Client Component 嵌在 Server Component 里,实现“壳在服务端、交互在客户端”。

四、开发体验与工程化

Next.js 在工程化上也做了很多封装,让你直接获得较好的 DX(Developer Experience)。(Next.js)

1. create-next-app 脚手架

用一个命令就能初始化:

npx create-next-app@latest my-app
# 或
pnpm create next-app my-app

支持可选项:

  • TypeScript
  • ESLint
  • Tailwind CSS
  • 实验特性等

2. 热更新与调试

  • Dev 模式下自动热更新(Fast Refresh),状态基本保持。

  • 内置:

    • 错误边界 UI
    • 开发提示(比如使用了不推荐的 API)

3. TypeScript & ESLint & Prettier

  • 官方模板默认把 TypeScript 配置好了。
  • 默认 ESLint 配置集成 Next.js 规则。
  • 和 Prettier / Husky / lint-staged 等前端工程化工具组合非常自然。

4. 与 Vercel 深度配合(但不限于 Vercel)

  • Next.js 由 Vercel 主导,自然在 Vercel 上零配置部署,非常丝滑。(维基百科)

  • 同时也支持:

    • 自建 Node.js 服务器
    • 其他平台(如 Render、Netlify、Railway 等)通过适配器或者 Build Adapter API 部署。(维基百科)

五、典型适用场景

结合现在 2025 年的实际应用,可以概括几个 Next.js 非常适合的场景:(raftlabs.com)

  1. 内容型网站(博客、文档、营销页、品牌站)

    • 静态生成 + ISR,性能和 SEO 都很好。
    • 搭配 MDX / CMS(如 Headless CMS)非常常见。
  2. SaaS / 后台管理系统 / 仪表盘

    • 复杂前端交互 + 登录态 + 权限控制 + API 调用
    • 可以用 SSR 提升“首屏可用速度”,App Router + Server Actions 简化后端逻辑。
  3. 电商网站

    • 商品详情页用 SSG + ISR
    • 购物车、结算等流程用 SSR/CSR
    • Next.js 官方和很多案例都是电商站点。
  4. 多租户平台 / B2B 产品

    • 通过中间件处理自定义域名、子域名的租户解析。
    • 路由和数据层结合,很适合你之前做的多租户 SaaS 设计思路。
  5. 混合应用(部分是静态内容,部分是 Web App)

    • 比如:首页 & 文档是静态的,管理后台是 SSR + SPA 体验。

六、Next.js 的优势与局限

优势

  1. 一体化解决方案
    从路由、渲染到 API、图片、字体、部署路径都给出了一套默认方案,对团队很友好。

  2. 性能导向
    SSR / SSG / ISR / 流式渲染 / RSC / Turbopack / 图片和字体优化等,把现代 Web 性能优化的“套路”全部内建。

  3. 全栈友好
    少量后端逻辑就可以直接写在 Next.js 项目的 Route Handlers / Server Actions 里,省去独立后端服务的复杂度。

  4. 生态与社区成熟
    大量教程、博客、模板、UI 组件库都对 Next.js 做了优化和封装,招聘也比较容易。(raftlabs.com)

局限 / 需要注意的点

  1. 概念较多,学习曲线有点陡

    • Pages Router vs App Router
    • SSR / SSG / ISR / CSR
    • Server / Client Components
    • Route Handlers / Server Actions / Middleware
      对于初学者来说,一次性全吃完会有些混乱。
  2. 对平台绑定的担忧

    • 虽然 Next.js 是开源的,但在 Vercel 上体验最好,有些高级特性(如 Edge Functions、图像优化)高度优化于 Vercel 平台,其他平台可能需要适配。(strapi.io)
  3. 对简单项目可能有点“重”

    • 如果只是一个极简单的静态页面或纯前端小工具,用纯 React + Vite / Astro 之类也许更轻量。

七、如何快速上手一个 Next.js 项目(App Router)

给你一个最小但“现代”的示例流程:

  1. 创建项目
npx create-next-app@latest my-next-app
# 选:TypeScript + ESLint + Tailwind(可选)
# 路由默认就会用 app/ 目录(新项目推荐)
  1. 查看基础目录
my-next-app/
  app/
    layout.tsx   // 全局布局,通常放导航、全局样式
    page.tsx     // 首页
  public/
  next.config.mjs
  tsconfig.json
  ...
  1. 写一个简单的首页

app/page.tsx

export default function Home() {
  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold">Hello Next.js</h1>
      <p className="mt-4">这是一个基于 App Router 的示例首页。</p>
    </main>
  );
}
  1. 添加一个带数据获取的页面

app/posts/page.tsx(Server Component):

async function getPosts() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts', {
    // 例如 60 秒再验证一次,实现 ISR 风格
    next: { revalidate: 60 },
  });
  return res.json();
}

export default async function PostsPage() {
  const posts = await getPosts();
  return (
    <main className="p-8">
      <h1 className="text-2xl font-bold mb-4">Posts</h1>
      <ul className="space-y-2">
        {posts.slice(0, 5).map((post: any) => (
          <li key={post.id} className="border p-2 rounded">
            <h2 className="font-semibold">{post.title}</h2>
            <p className="text-sm text-gray-600">{post.body}</p>
          </li>
        ))}
      </ul>
    </main>
  );
}
  1. 添加一个 Client Component

app/components/Counter.tsx

"use client";

import { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button
      onClick={() => setCount(c => c + 1)}
      className="mt-4 px-4 py-2 border rounded"
    >
      点击次数:{count}
    </button>
  );
}

app/page.tsx 中使用:

import { Counter } from "./components/Counter";

export default function Home() {
  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold">Hello Next.js</h1>
      <Counter />
    </main>
  );
}

这样你就已经实践了:

  • App Router 目录结构
  • Server Component 数据获取 + ISR
  • Client Component 交互逻辑

总结

如果一句话概括:

Next.js = “带路由 + 渲染策略 + 性能优化 + API + 部署路径”的 React 全栈框架,App Router + Server Components 是它未来几年的核心方向。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页