概念

发布于 2026-06-01更新于 2026-07-16

use client

声明 Client Component 边界

厘清概念

CSR

Client-Side Rendering,客户端渲染。

核心定义:页面主要内容由浏览器中的 JavaScript 执行后渲染出来,数据来源可以是:

  • fetch;
  • 数据写死在 JS 中;
  • 其他类似;

CSR = HTML 的主要 UI 内容依赖浏览器 JS 执行后产生。

bundle

原意:捆、束、一包东西;在前端工程里,可以理解为:经过构建工具处理后,打包给浏览器的一组 JavaScript 代码/资源。

比如:

import React from 'react'
import Button from './Button'
import { formatDate } from './utils'

这些代码散落在:

page.tsx
Button.tsx
utils.ts
React
第三方依赖
...

构建工具会分析这些模块之间的依赖关系:

源代码模块
   ↓
dependency graph
   ↓
编译 / 转换 / 优化 / 拆分
   ↓
一个或多个 JS 文件

最终交付给浏览器的代码,通常就是:JavaScript bundle、client bundle、bundle size等;

Next.js 不会粗暴地把所有东西真的塞进一个 bundle.js;实际上会进行 code splitting/chunking,产生多个 chunk。

因此,bundle 的理解就是:打包后的客户端代码集合。

prerender

pre + render
预先 + 渲染

在用户真正访问页面之前,提前把页面渲染出来。是 Web / SSR / SSG 领域的通用概念。

Hydration

hydrate 本身有:给……补充水分。

可以想象 build 得到的 HTML 是一个:干的页面,已经有:标签、文字、结构、内容,但是缺少 React 客户端行为。

浏览器加载 JS 后,React 对已有 HTML 进行 hydration:不是把页面推倒重建,而是在已有 HTML 基础上注入/恢复客户端能力。

hydration 的过程中,客户端第一次 render 的结果确实需要和服务端/预渲染得到的 HTML 对得上。

因此翻译为:水合,是 React SSR/预渲染体系里的核心机制,React 在浏览器中接管已经存在的 HTML,并把它变成可交互的 React 应用。

已有 HTML

<button>0</button>
      │
      │ 下载 Client JS
      ↓
React 执行
      │
      ↓
Hydration
      │
      ├── 建立 React 组件树
      ├── 将 React 与已有 DOM 对应起来
      ├── 建立事件处理
      └── 恢复交互能力
             ↓
        button 可以点击

理解

最直白的理解:声明 Client Component 边界;

  • 与 "Client Component" 和 "CSR 纯客户端渲染"分开,不是一回事;
  • 表示这个组件需要客户端 JavaScript 能力,不是表示这个组件只能在客户端生成 HTML;

如何理解?

静态导出时,Client Components 也会在 next build 阶段 prerender;最终仍然会产生用于首次访问的静态 HTML

'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' 本质是在告诉 Next.js:从这个文件开始,建立一个 Server / Client 的边界;这个模块及其客户端依赖需要进入浏览器 JavaScript bundle。

  • Next.js 的 page.tsx 和 layout.tsx 默认都是 Server Components。只有当你需要客户端能力时,才应该建立 'use client' 边界。

比如:

page.tsx                Server Component
│
├── Article.tsx         Server Component
│
└── LikeButton.tsx      Client Component
      ↑
      'use client'

大致流程如下:

next build
   │
   ├── Server Components 执行
   │
   ├── Client Components 也参与预渲染
   │
   ↓
生成静态 HTML
   +
生成 Client Component 对应 JS
   ↓
浏览器
   │
   ├── 先显示 HTML
   └── JS hydration
          ↓
       onClick / state / effect 生效

以下情况需要 Client Component:

  • useState
  • useEffect
  • 事件处理,例如 onClick、onChange
  • 浏览器 API,例如 window、document、localStorage、Geolocation
  • 依赖这些能力的 custom hooks

凡是依赖浏览器运行时状态、生命周期、事件或 Browser API 的 UI,一般需要位于 Client Component 边界之内。

'use client'
 
function Counter() {
  const [count, setCount] = useState(0)
 
  useEffect(() => {
    console.log('browser')
  }, [])
 
  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  )
}

分成:

BUILD
────────────────
 
Counter render
    ↓
<button>0</button>
    ↓
写入 HTML
 
 
BROWSER
────────────────
 
HTML 立即显示
    ↓
下载 Counter JS
    ↓
React hydration
    ↓
useEffect 执行
    ↓
onClick 开始工作
    ↓
useState 可以变化

影响 SEO、首屏内容与性能不在 use client,而在:核心内容是不是 build 时就已经进入 HTML

'use client'
 
function Article() {
  return (
    <article>
      <h1>TypeScript 基础</h1>
      <p>这是一篇文章……</p>
    </article>
  )
}

仍然会 prerender 成 HTML,搜索引擎拿到的 HTML 本身就可能包含:

<h1>TypeScript 基础</h1>
<p>这是一篇文章……</p>

需要注意的是如下的写法:

'use client'
 
function Article() {
  const [content, setContent] = useState('')
 
  useEffect(() => {
    fetch('/article.json')
      .then(...)
      .then(setContent)
  }, [])
 
  return <article>{content}</article>
}

build 阶段可能只有:

<article></article>

浏览器执行 JS 后才变成:

<article>
  很多正文……
</article>
            Next.js App Router
 
                    Component
                        │
            ┌───────────┴───────────┐
            │                       │
    Server Component        Client Component
        默认                     'use client'
            │                       │
build/server 执行           需要 browser JS
            │                       │
            └───────────┬───────────┘
                        │
                    prerender
                        │
                    HTML
                        │
                    浏览器加载
                        │
                Client JS hydration
                        │
                    可交互