ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Langfuse 前端数据请求去重实践:基于 Vercel SWR 最佳实践规则(client-swr-dedup)的解读与落地

Langfuse 前端数据请求去重实践:基于 Vercel SWR 最佳实践规则(client-swr-dedup)的解读与落地 Langfuse 前端数据请求去重实践基于 Vercel SWR 最佳实践规则client-swr-dedup的解读与落地【免费下载链接】langfuse Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse导读本文以 Langfuse 仓库内web/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md规则文档为核心深入讲解客户端数据请求去重的核心机制SWR 如何在同一页面多个组件实例共享同一请求、如何区分可变数据与不可变数据、以及如何安全地执行写操作mutation。读完本文你将掌握从useEffect fetch手写数据请求向 SWR 声明式数据请求迁移的完整思路并了解该规则在 Langfuse 当前前端技术栈tRPC React Query中的现实定位与借鉴价值。一、规则文档定位Vercel 前端最佳实践技能库中的一环该规则文档位于 Langfuse 仓库的 Vercel 技能目录中web/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md。同目录下还包含 50 余条针对 React / Next.js 的性能优化规则覆盖消除瀑布流async-*、包体积优化bundle-*、服务端性能server-*、客户端数据请求client-*、重渲染优化rerender-*、渲染性能rendering-*、JavaScript 性能js-*与进阶模式advanced-*八个类别。规则文档的 frontmatter 元数据明确了其定位--- title: Use SWR for Automatic Deduplication impact: MEDIUM-HIGH impactDescription: automatic deduplication tags: client, swr, deduplication,>function UserList() { const [users, setUsers] useState([]) useEffect(() { fetch(/api/users) .then(r r.json()) .then(setUsers) }, []) }这段代码的问题可以拆解为三层无去重如果UserList在同一页面被渲染多次例如列表、统计卡片、下拉菜单各自引用同一数据源每个组件实例都会独立发起一次/api/users请求。规则文档明确点出这一点Incorrect (no deduplication, each instance fetches)。无缓存组件卸载后数据即丢失重新挂载必然重新请求无法复用已获取的数据。手动状态管理loading、error、data三种状态全部需要手写代码冗余且容易遗漏边界处理。这种模式在 Langfuse 这种以数据看板、Trace 列表、评估结果表格为核心界面的产品中尤其值得警惕——同一份用户/项目/评分数据往往会被页面内多个组件消费。三、正确姿势useSWR 让多个实例共享一次请求规则文档给出的核心解法是引入 SWR名称取自 HTTP 缓存策略 stale-while-revalidate即先返回旧数据后台重新验证import useSWR from swr function UserList() { const { data: users } useSWR(/api/users, fetcher) }其工作模型可以概括为Key 即缓存标识第一个参数/api/users是请求的唯一 keySWR 全局缓存以 key 为索引。规则文档特别强调multiple instances share one request——只要 key 相同同一时间窗口内的多个useSWR调用只会触发一次真实网络请求其余实例直接复用同一份数据。fetcher 为请求执行函数第二个参数负责真正发起请求并返回数据例如const fetcher (url: string) fetch(url).then(r r.json())。跨组件实例的全局缓存缓存由 SWR 的全局缓存区cache provider持有而非组件本地状态因此不同组件、不同页面间可以共享。自动重新验证在保持陈旧数据可用的同时SWR 会在重新聚焦窗口、网络重连等时机自动发起后台验证保证数据新鲜度。与 React Query 的对照Langfuse 前端实际使用的tanstack/react-query见 web/package.json采用了完全同构的抽象useQuery({ queryKey, queryFn })中queryKey对应 SWR 的 keyqueryFn对应 fetcherReact Query 同样提供跨组件去重同一queryKey同时被多个组件订阅时只发一次请求、全局缓存与后台重新验证。因此本文规则中以 key 去重、以全局缓存共享的思想可以直接迁移到 Langfuse 现有的 tRPC React Query hooks 上——例如通过 tRPC 的api.users.all.useQuery()在同一页面多处调用React Query 会自动合并为一次请求。四、不可变数据useImmutableSWR 关闭自动重新验证对于配置类、静态内容等不会在客户端生命周期内变化的数据规则文档推荐使用不可变模式的封装import { useImmutableSWR } from /lib/swr function StaticContent() { const { data } useImmutableSWR(/api/config, fetcher) }useImmutableSWR本质上是useSWR的一个预配置变体——它基于useSWR的revalidateIfStale、revalidateOnFocus、revalidateOnReconnect等选项将默认值关闭使数据在首次加载后只读缓存、不再触发后台重新验证。这样既保留了请求去重与缓存的能力又避免了不必要的重复请求。使用场景举例全局配置项主题、特性开关、静态元信息版本号、环境标签等低频变化数据服务端已保证不变的引用数据。对照 Langfuse仓库中存在大量类似只读配置型的数据消费点。对于这类数据如果使用 React Query等价做法是在useQuery中设置staleTime: Infinity与refetchOnWindowFocus: false达到加载一次、长期复用的效果。五、写操作useSWRMutation 与读请求解耦规则文档的第三个示例面向变更操作创建、更新、删除它强调不要把 mutation 塞进普通的useSWR请求流程中而是使用独立的 mutation APIimport { useSWRMutation } from swr/mutation function UpdateButton() { const { trigger } useSWRMutation(/api/user, updateUser) return button onClick{() trigger()}Update/button }要点拆解useSWRMutation与useSWR使用相同的 key 体系因此 mutation 完成后天然可以结合mutate()等工具触发对应 key 的重新验证实现写后更新读缓存的数据一致性闭环trigger由用户显式调用例如点击事件不会在组件挂载时自动执行避免页面加载即产生副作用请求updateUser接收 key 与触发参数执行真实的写请求并返回结果。这套读用 useSWR、写用 useSWRMutation、写后按需失效缓存的模式与 React Query 中useMutationqueryClient.invalidateQueries()的组合一一对应。在 Langfuse 的 tRPC 层中等价形态是api.xxx.update.useMutation()配合成功回调里对相关查询做失效处理。六、规则对比速查什么时候该用什么数据形态反模式不推荐推荐做法关键收益任意共享数据每个实例useEffect fetchuseSWR(key, fetcher)请求去重、全局缓存、自动重新验证不可变/静态数据每次挂载重新请求useImmutableSWR(key, fetcher)首次加载后不再重复请求写操作混入useSWR或在 effect 中触发useSWRMutation(key, updater)手动trigger()读写解耦、按需触发、可失效缓存现有 React Query 栈手写 fetch 手动状态useQuery({ queryKey, queryFn })useMutation与 Langfuse 当前 tRPC React Query 栈一致七、落地检查清单结合规则文档与 Langfuse 仓库现状在做代码评审或重构时可按以下清单自查同一数据是否被多个组件实例请求多次若是检查是否已使用以 key 为单位的全局缓存抽象SWR 的useSWR或 React Query 的useQuery。静态数据是否仍在被重新验证对配置类数据使用useImmutableSWR或设置staleTime: Infinity。写操作是否在挂载时被意外触发useSWRMutation/useMutation的trigger/mutate必须由事件驱动。变更后读缓存是否同步失效mutation 成功后需按 key 触发重新验证避免 UI 展示陈旧数据。是否引入了不必要的 effectuseEffect fetch模式中所有请求都发生在 effect 中应尽量替换为声明式数据请求 hooks减少状态同步代码这一思路也与同目录下 rerender-move-effect-to-event.md 等规则的少用 effect取向一致。八、进一步阅读规则原文web/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md技能总览含全部 57 条规则的优先级表web/.agents/skills/vercel-react-best-practices/SKILL.md完整规则汇编该文档的 AGENTS 版本第 4.3 节即本节规则的展开版web/.agents/skills/vercel-react-best-practices/AGENTS.mdLangfuse 前端数据层现状tRPC 客户端入口 web/src/utils/api.ts依赖声明见 web/package.jsontanstack/react-query、trpc/client、trpc/next等相关配套规则客户端事件监听去重 client-event-listeners.md、localStorage 版本化 client-localstorage-schema.md总结而言client-swr-dedup规则的核心是一句话让数据请求以 key 为单位去重、以全局缓存共享、以声明式 hooks 替代手写 effect。无论你是在 SWR 技术栈中直接套用还是在 Langfuse 现有的 tRPC React Query 栈中吸收其思想这条规则都能显著减少冗余网络请求、降低状态管理复杂度让数据密集型前端页面更快、更稳。【免费下载链接】langfuse Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进