- 人工智能
- 大模型
- AI 应用
- 前端
- 后端
【免费下载链接】BibiGPT-v1
BibiGPT v1 · one-Click AI Summary for Audio/Video & Chat with Learning Content: Bilibili | YouTube | Tweet丨TikTok丨Dropbox丨Google Drive丨Local files | Websites丨Podcasts | Meetings | Lectures, etc. 音视频内容 AI 一键总结 & 对话:哔哩哔哩丨YouTube丨推特丨小红书丨抖音丨快手丨百度网盘丨阿里云盘丨网页丨播客丨会议丨本地文件等 (原 BiliGPT 省流神器 & AI课代表)
本文以 BibiGPT-v1(哔哩哔哩丨YouTube 等音视频内容的一键 AI 总结与对话应用)仓库中的.agents/skills/next-best-practices/directives.md为骨架,系统梳理 React 与 Next.js 的三大指令('use client'、'use server'、'use cache'):它们各自标记什么、在什么场景下必须使用、边界在哪里,并结合仓库源码展示真实项目中的落地形态与限制。读完你将掌握在客户端组件、Server Action 与缓存组件之间正确划分职责的完整判断方法,并能直接套用本文的检测清单审查自己的 Next.js 项目。
一、指令总览:三者在组件模型中的分工
在 React Server Components(RSC)架构下,模块顶部的"指令字符串"是声明代码执行边界的元信息,它们不是普通导入,而是编译期与运行期都会识别、并决定代码归属(客户端 bundle 还是服务端)的关键标记。directives.md将指令分为两组:
- React 指令:
'use client'与'use server',属于 React 运行时本身的能力,与具体的 Next.js 版本无关; - Next.js 指令:
'use cache',属于 Next.js Cache Components 的组成部分,依赖框架配置(cacheComponents: true)。
在 BibiGPT-v1 仓库中,项目采用pages/目录结构的 Pages Router(见 pages/),并使用react: 18.2.0、next: ^16.1.6(见 package.json)。需要特别说明的是:'use server'与'use cache'面向的是 App Router 与 RSC 模型,本项目目前并未使用这两种指令(全仓搜索无任何命中),其服务端职责由pages/api/下的 Route Handlers 承担。因此本文对后两者的讲解以能力与配置原理为主,并给出迁移到 App Router 时的落地指引;而'use client'则在仓库中被广泛使用,我们将以其为实战主线展开。
二、'use client':标记 Client Component 边界
2.1 指令语义与适用场景
directives.md明确指出:'use client'将组件标记为 Client Component(注意,这是 React 指令,并非 Next.js 专属)。它必须出现在以下三类代码所在的模块顶部:
- React hooks:
useState、useEffect、useContext等; - 事件处理器:
onClick、onChange等交互回调; - 浏览器 API:
window、localStorage、document等仅存在于客户端的对象。
原文档给出的最小可运行示例:
'use client' import { useState } from 'react' export function Counter() { const [count, setCount] = useState(0) return <button onClick={() => setCount(count + 1)}>{count}</button> }'use client'是"模块级"声明,它标记的是该模块及其传递依赖中所有组件的边界:一旦模块被打上此标记,其内部代码(包括没有显式标记的子组件)都会被纳入客户端 bundle。反过来,Server Component 中导入一个 Client Component 是完全合法的,反之则不允许——客户端模块不能直接导入服务端模块。
2.2 BibiGPT-v1 中的实际应用盘点
在仓库中,'use client'出现在 10 个组件文件的首行,构成清晰的"客户端工具层":
- 9 个基础 UI 组件(shadcn/Radix UI 风格):components/ui/command.tsx、dialog.tsx、dropdown-menu.tsx、label.tsx、select.tsx、slider.tsx、switch.tsx、toaster.tsx、tooltip.tsx;
- 主题切换组件:components/mode-toggle.tsx。
以 components/mode-toggle.tsx 为例,它同时覆盖了三类"必须走客户端"的场景:使用useTheme()这个 React hook、通过setTheme('light' | 'dark' | 'system')响应点击事件、并依赖next-themes操作class属性与浏览器存储。这正好是'use client'三条判据的教科书级案例。
2.3 实战陷阱:SSR 与浏览器 API 的安全访问模式
'use client'组件在服务端预渲染(SSR)阶段同样会被执行,因此不能认为打上标记就可以无脑访问浏览器 API。仓库中的自定义 hook hooks/useLocalStorage.ts 给出了标准防护模式:
export function useLocalStorage<T>(key: string, initialValue?: T) { const [storedValue, setStoredValue] = React.useState<T>(() => { if (typeof window === 'undefined') { return initialValue // SSR 阶段直接返回初始值 } try { const item = window.localStorage.getItem(key) return item ? JSON.parse(item) : initialValue } catch (error) { console.error(error) return initialValue } }) // ... }关键点有三:其一,typeof window === 'undefined'是判断是否处于服务端渲染的标准写法;其二,读取操作放在useState的惰性初始化函数中,保证只在首次渲染执行一次;其三,JSON.parse包在try/catch中,避免脏数据导致整个组件崩溃。该 hook 被 hooks/useConfig.ts 复用以持久化 Segment 埋点配置,是"客户端组件 + 安全浏览器访问"的组合范本。
类似地,components/CommandMenu.tsx 在useEffect中注册document键盘事件(Cmd/Ctrl + K唤起命令面板),并在清理函数中正确移除监听——事件处理器与浏览器 API 都只在客户端生效,且清理逻辑避免内存泄漏:
const [open, setOpen] = React.useState(false) React.useEffect(() => { const down = (e: KeyboardEvent) => { if (e.key === 'k' && e.metaKey) { setOpen((open) => !open) } } document.addEventListener('keydown', down) return () => document.removeEventListener('keydown', down) }, [])而 pages/index.tsx 则展示了另一个典型边界:useState+useEffect异步加载 SegmentAnalyticsBrowser后写入window.analytics。这意味着首页组件实质上是客户端交互密集型组件,若迁移到 App Router,同样需要'use client'标记。
2.4 判定清单:何时必须加'use client'
综合原文档判据与仓库实践,写出如下自检清单:
| 代码特征 | 示例(来自仓库) | 是否需要'use client' |
|---|---|---|
| 使用 React hooks | useState/useEffect/useTheme | 是 |
| 绑定事件处理器 | onClick、addEventListener | 是 |
| 访问浏览器 API | window、localStorage、document | 是 |
| 依赖浏览器端库 | next-themes、Segment Analytics | 是 |
| 纯展示、无交互的静态内容 | 页面骨架、布局容器 | 否(保持 Server Component) |
三、'use server':标记 Server Action
3.1 两种合法写法
directives.md指出,'use server'将函数标记为 Server Action,且该函数可以传递给 Client Component调用。它支持两种形态。
形态一:模块顶部声明(整个模块导出的异步函数均为 Server Action):
'use server' export async function submitForm(formData: FormData) { // Runs on server }形态二:Server Component 内联声明(只标记单个函数):
export default function Page() { async function submit() { 'use server' // Runs on server } return <form action={submit}>...</form> }两种写法的共同约束是:Server Action 必须是async函数,且其入参、返回值都必须可序列化(即可以被网络传输,典型如FormData、字符串、JSON 兼容对象),这正是 .agents/skills/next-best-practices/rsc-boundaries.md 中"Server Action 异常"检测项关注的非序列化 props 问题。
3.2 在 BibiGPT-v1 中的位置与限制
如前所述,本仓库是 Pages Router 项目,全仓搜索use server无任何命中,Server Actions 并未启用。服务端逻辑统一收敛在pages/api/下的 Route Handlers 中,典型如 pages/api/chat.ts:
export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method !== 'POST') { res.setHeader('Allow', 'POST') return res.status(405).send(toHttpErrorMessage(405, 'Method Not Allowed')) } const { videoConfig, userConfig } = req.body as ChatBody // ... }该端点承担了"抓取字幕 → 构建 OpenAI 请求 → 流式返回总结"的完整服务端链路(实现见 lib/openai/buildSummarizeRequest.ts 与 lib/openai/fetchOpenAIResult.ts),客户端则通过 hooks/useSummarize.ts 中的useChat+TextStreamChatTransport('/api/chat')发起调用。这是一个重要的架构判断点:Pages Router 下服务端逻辑用 API Routes 表达,等价能力在 App Router 中才迁移为 Server Actions 或 Route Handlers。若未来升级到 App Router,可将纯数据型交互(如写入用户配置)收敛为 Server Action,而把流式总结这类需要自定义 HTTP 头与流控的接口保留为 Route Handler。
四、'use cache':Next.js Cache Components 的缓存指令
4.1 指令语义与配置前提
directives.md说明:'use cache'标记函数或组件以启用缓存,是 Next.js Cache Components 的一部分:
'use cache' export async function getCachedData() { return await fetchData() }它必须配合next.config.ts中的cacheComponents: true才能生效:
// next.config.ts const nextConfig = { cacheComponents: true, }启用后,被标记的函数结果会被框架级缓存复用,从而避免重复的数据获取与渲染开销。
4.2 仓库现状核查
检查 BibiGPT-v1 的 next.config.js:其中只配置了reactStrictMode: true、images.remotePatterns(Supabase、bibigpt.co、dicebear 头像等远程图片域名)以及async rewrites()(将/api/:path*代理到INTERNAL_API_HOSTNAME),并未开启cacheComponents。这与"项目未使用'use cache'"的事实互相印证——缓存指令既依赖 App Router 的 Cache Components 模型,也需要显式开启配置项,二者缺一不可。
同时,原文档明确指出:'use cache'的进阶用法(缓存配置文件、cacheLife()生命周期、cacheTag()打标签、updateTag()失效更新)超出了该文档范围,需参考仓库内的next-cache-componentsskill 专题文档。本仓库的 .agents/skills/next-best-practices/ 目录中还包含同系列专题,例如数据模式(data-patterns.md)、自托管(self-hosting.md)等,可作为进一步学习的索引。
4.3 适用前提与限制总结
| 条件 | 说明 |
|---|---|
| 架构前提 | 仅适用于 App Router 与 RSC 模型,Pages Router 项目无法使用 |
| 配置前提 | 必须在next.config.ts中设置cacheComponents: true |
| 生效对象 | 异步函数、组件、数据获取逻辑 |
| 扩展能力 | cacheLife()控制缓存时长,cacheTag()/updateTag()实现标签化失效 |
| 本仓库现状 | next.config.js未开启该配置,项目中无任何'use cache'使用点 |
五、三指令速查与迁移建议
最后用一张对照表收束全文,也作为日常编码的快速参考:
| 指令 | 归属 | 标记对象 | 关键场景 | 配置要求 | BibiGPT-v1 现状 |
|---|---|---|---|---|---|
'use client' | React | 组件模块 | hooks、事件、浏览器 API | 无 | 10 个组件文件已使用 |
'use server' | React | async 函数 | 可传给客户端调用的服务端逻辑 | 无 | 未使用(Pages Router 用 API Routes) |
'use cache' | Next.js | 函数/组件 | 缓存数据获取与渲染 | cacheComponents: true | 未使用(未开启配置) |
基于以上分析,可以给出三条可执行的工程建议:其一,在 Pages Router 项目中,遇到 hooks/事件/浏览器 API 时果断加'use client',并沿用typeof window === 'undefined'的 SSR 防护模式(参照 hooks/useLocalStorage.ts);其二,服务端逻辑在 Pages Router 下继续使用pages/api/Route Handlers,待升级 App Router 后再评估是否引入 Server Actions;其三,引入'use cache'前务必先确认架构已切换为 App Router、并在next.config.ts开启cacheComponents,避免"指令写了却不生效"的静默陷阱。
- 人工智能
- 大模型
- AI 应用
- 前端
- 后端
【免费下载链接】BibiGPT-v1
BibiGPT v1 · one-Click AI Summary for Audio/Video & Chat with Learning Content: Bilibili | YouTube | Tweet丨TikTok丨Dropbox丨Google Drive丨Local files | Websites丨Podcasts | Meetings | Lectures, etc. 音视频内容 AI 一键总结 & 对话:哔哩哔哩丨YouTube丨推特丨小红书丨抖音丨快手丨百度网盘丨阿里云盘丨网页丨播客丨会议丨本地文件等 (原 BiliGPT 省流神器 & AI课代表)
相关推荐
大麦抢票自动化工具实操手册:从环境自检到开抢的 7 步流程
大麦抢票自动化工具实操手册:从环境自检到开抢的 7 步流程 大麦抢票自动化工具用 Python 驱动 Selenium 和 Appium,帮你在开售瞬间自动完成
前端UI组件Next.js 指令完全指南:在 next-shadcn-dashboard-starter 中正确使用 `'use client'`、`'use server'` 与 `'use cache'`
Next.js 指令完全指南:在 next shadcn dashboard starter 中正确使用 'use client' 、 'use server'
前端UI组件Agent 操作界面(Agent Interfaces)实战指南:Browser Use · Computer Use · Sandbox 的最小门选择与安全边界
Agent 操作界面(Agent Interfaces)实战指南:Browser Use · Computer Use · Sandbox 的最小门选择与安全边
教程文档AI Agent人工智能大模型
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考