Cherry Studio 工程实践:彻底搞懂 RSC Props 按引用去重,消灭重复序列化冗余
Cherry Studio 工程实践彻底搞懂 RSC Props 按引用去重消灭重复序列化冗余【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio导读本指南围绕 Cherry Studio 仓库中随附的 Vercel React 性能最佳实践技能规则 server-dedup-props.md 展开深入讲解 React Server ComponentsRSC跨服务端/客户端边界序列化时按对象引用去重的核心机制。读完本文你将掌握为什么usernames与usernames.toSorted()同时传给客户端组件会让网络载荷翻倍、哪些数据类型的重复引用影响最大、以及如何在服务端与客户端之间正确划分数据变换职责从而在不改变功能的前提下显著减小 RSC 传输体积。一、背景RSC 边界的序列化与去重机制在 React Server Components 架构中服务端组件渲染完成后需要把传递给客户端组件use client的 props 序列化为字符串嵌入 HTML 响应以及后续的 RSC 请求中。这部分序列化数据会直接叠加到页面体积和加载时间上——正如姊妹规则 server-serialization.md 所述服务端与客户端的边界会把对象的所有属性序列化成字符串因此size matters a lot只应传递客户端真正用到的字段。关键机制在于RSC → 客户端的序列化去重是按对象引用reference而非按值value进行的。也就是说同一个引用被传给客户端组件只序列化一次一旦产生新的引用即使内容完全相同就会再次完整序列化一份。这条规则正是本仓库技能库中server-前缀Server-Side PerformanceHIGH 优先级类别的第 3.2 条规则定位为 LOW 影响、用于通过避免重复序列化来减小网络载荷。二、反模式示例服务端重复传递派生数组先看最常见的错误写法。下面这段代码把同一个数组的原始版本和排序版本同时传给了客户端组件// RSC: sends 6 strings (2 arrays × 3 items) ClientList usernames{usernames} usernamesOrdered{usernames.toSorted()} /这里的usernames是一个长度为 3 的字符串数组。usernames.toSorted()会创建一个全新的数组引用其内容虽然与原始数组完全一致但引用不同。因此 RSC 序列化器无法识别它们其实是同一批数据结果原始数组序列化一次3 个字符串排序后的新数组引用再次序列化一次又是 3 个字符串。最终网络载荷中出现了6 个字符串而客户端实际只需要其中一份数据。三、正确做法数据变换下放到客户端正确的做法是让服务端只传递一次原始引用把排序这类派生变换放到客户端组件内完成// RSC: send once ClientList usernames{usernames} / // Client: transform there use client const sorted useMemo(() [...usernames].sort(), [usernames])这样 RSC 只序列化 3 个字符串客户端在本地完成排序。这里有两个细节值得注意客户端排序用[...usernames].sort()而不是usernames.sort().sort()是原地in-place修改方法会直接改动 props 数组破坏 React 的不可变模型。这一点与技能库中 js-tosorted-immutable.md 规则的警告一致——Props/state 的变更会破坏 React 的不可变模型React 期望 props 与 state 被视为只读。在支持新式方法的现代浏览器Chrome 110、Safari 16、Firefox 115、Node.js 20中也可改用usernames.toSorted()旧环境则用[...items].sort()兜底。客户端派生用useMemo包裹useMemo(() [...usernames].sort(), [usernames])保证只有当usernames引用变化时才重新排序避免每次渲染都产生新的排序结果。四、嵌套去重的行为差异按数据类型评估影响去重机制是递归生效的但不同数据类型的重复成本差异极大规则文档给出了两组对照示例// string[] - duplicates everything usernames{[a,b]} sorted{usernames.toSorted()} // sends 4 strings // object[] - duplicates array structure only users{[{id:1},{id:2}]} sorted{users.toSorted()} // sends 2 arrays 2 unique objects (not 4)对影响程度可以做出如下判断string[]、number[]、boolean[]这类原始类型数组影响为HIGH——数组本身与其中的全部原始值都会被完整重复序列化。因为原始值没有引用概念无法通过引用去重只能逐字复制。object[]这类对象数组影响为LOW——数组结构外层引用会被重复序列化但嵌套对象是按引用去重的所以toSorted()前后数组里的对象元素仍是同一批引用不会被二次复制。因此是2 个数组 2 个唯一对象而不是 4 份对象。这条结论可以直接指导我们做成本决策当数据是原始类型数组时在服务端多做一次派生变换的代价是成倍的网络字节当数据是对象数组时代价相对可控但仍不值得白白浪费。五、打破去重的操作清单识别新引用制造机只要产生了新引用去重即失效。规则文档给出了一份明确的清单数组类创建新引用.toSorted().filter().map().slice()展开语法[...arr]对象类创建新引用展开语法{...obj}Object.assign()structuredClone()JSON.parse(JSON.stringify())把这些操作放在服务端渲染路径上就意味着每次调用都会生成一个无法与原始数据共享序列化的新对象。特别注意JSON.parse(JSON.stringify())——它不仅是深拷贝而且会丢弃函数、undefined、循环引用等无法序列化的值同时产生一个彻底的全新引用是去重的最大杀手。六、更多对照示例对象属性拆分同样有害除了数组派生把对象属性拆出来单独传递同样会造成重复序列化// ❌ Bad C users{users} active{users.filter(u u.active)} / C product{product} productName{product.name} / // ✅ Good C users{users} / C product{product} / // Do filtering/destructuring in client反例中C users{users} active{users.filter(...)} /users与users.filter(...)是两个引用序列化两份C product{product} productName{product.name} /整个product对象序列化一次product.name这个字符串又单独序列化一次——而它明明已经是product对象内部的一个属性。正确写法是只传原始引用users与product过滤、解构等派生工作全部交给客户端组件内部完成。七、规则例外何时允许在服务端传派生数据规则文档特别给出了例外情况当变换本身非常昂贵或者客户端根本不需要原始数据时应当在服务端传递派生后的结果。例如变换需要访问服务端才有的大数据、需要多次网络往返或高计算量此时在客户端重复计算反而更浪费客户端只需要已排序/已过滤的结果不需要原始数组——此时只传一份派生结果是最优的因为根本没有两份数据需要去重。判断标准可以归纳为一句话只有当同一份原始数据要被客户端同时以多种形态使用时重复序列化才是需要避免的浪费如果客户端只需要单一派生形态直接在服务端算好再传。八、协同规则把 RSC 边界数据传输压到最低本规则并非孤立存在它与技能库 SKILL.md 中 Server-Side PerformanceHIGH分类下的多条规则构成一套完整打法减少总量先按 server-serialization.md 的规则只传递客户端实际用到的字段。例如服务端fetchUser()返回 50 个字段、客户端只用name时直接传Profile name{user.name} /而不是整个user对象——把 50 个字段压到 1 个字段。消除重复再按本规则server-dedup-props同一个引用只传一次派生形态留给客户端。请求级去重如果担心客户端重复渲染导致多次派生计算可结合 client-swr-dedup.md 使用 SWR 对数据请求本身去重多个组件实例共享同一次请求。服务端去重若同一请求内多处需要相同数据可参考 server-cache-react.md 用React.cache()做请求内去重注意其基于Object.is的浅比较内联对象会永远 miss。九、在 Cherry Studio 仓库中的落地方式Cherry Studio 仓库将这套规则以技能skill形式固化在 .agents/skills/vercel-react-best-practices 目录下每条规则一个 Markdown 文件带title/impact/impactDescription/tags的 frontmatter通过 README.md 中描述的pnpm build编译合并进AGENTS.md并支持pnpm validate校验、pnpm extract-tests抽取测试用例。规则文件命名前缀决定了所属分类server-对应 Server-Side Performancejs-对应 JavaScript Performanceclient-对应 Client-Side Data Fetchingrerender-对应 Re-render Optimization等等。Impact 分级CRITICAL / HIGH / MEDIUM-HIGH / MEDIUM / LOW-MEDIUM / LOW用于指导自动化重构的优先级本规则属于 LOW 增量优化通常在完成 HIGH/CRITICAL 级优化如并行抓取、包体积、序列化瘦身之后作为最后一公里的净载荷削减手段落地。在实际开发中审查任何从 Server Component 传到use client组件的 props 时都可以对照本文的检查清单同一份数据是否被传了多次派生变换是否留在了服务端如果是就把变换挪到客户端让 RSC 序列化器用引用去重为你省下每一份重复的字节。【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

IntelliJ IDEA高效配置指南:从编码到构建,全面提升开发效率

IntelliJ IDEA高效配置指南:从编码到构建,全面提升开发效率

很多人装好 IntelliJ IDEA 之后就直接开写代码了,觉得"能跑就行"。但用久了你会发现,那些真正影响效率的往往不是功能本身,而是你有没有把工具调到顺手的状态。我这些年折腾下来最大的感受就是:IDEA 默认配置只保证可用…

2026/9/18 12:37:31 阅读更多 →
PC3000固件级修盘:SA区、LDR加载与缺陷表管理

PC3000固件级修盘:SA区、LDR加载与缺陷表管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 12:37:31 阅读更多 →
Grafana Tempo 排查:如何确认 Alloy 是否成功把 Trace 推送到了后端

Grafana Tempo 排查:如何确认 Alloy 是否成功把 Trace 推送到了后端

Grafana Tempo 排查:如何确认 Alloy 是否成功把 Trace 推送到了后端 【免费下载链接】tempo Grafana Tempo is a high volume, minimal dependency distributed tracing backend. 项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo Grafana Alloy…

2026/9/18 12:37:31 阅读更多 →

最新新闻

人工智能优化税务审计与合规:从规则引擎到可解释风险排序模型

人工智能优化税务审计与合规:从规则引擎到可解释风险排序模型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 17:12:43 阅读更多 →
Kettle安装与使用全指南:ETL入门、环境配置、数据库驱动及常见报错解决

Kettle安装与使用全指南:ETL入门、环境配置、数据库驱动及常见报错解决

做数据相关工作的人,基本都绕不开 ETL 这三个字母。而 Kettle(现在官方叫 Pentaho Data Integration,大家还是习惯叫 Kettle)应该是最适合入门、也是最常用的可视化 ETL 工具之一。这篇装教程不是简单地让你“下一步下一步”&…

2026/9/19 17:12:43 阅读更多 →
Gemini CLI 跑 tools.ts 工具调用,Base URL 填 TaoToken

Gemini CLI 跑 tools.ts 工具调用,Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 17:12:43 阅读更多 →
餐厅点餐系统毕业设计:从建表、并发控制到论文写作完整指南

餐厅点餐系统毕业设计:从建表、并发控制到论文写作完整指南

简介:这是一份西北工业大学网络教育学院软件工程专业的餐厅点餐系统毕业设计文档,适合高校计算机相关专业学生撰写论文或课程设计时参考。资源为单个doc格式文件,大小4.37MB,完整收录了毕业论文任务书、摘要、目录、绪论、需求分析…

2026/9/19 17:12:43 阅读更多 →
Dify 自定义模型供应商,Base URL 填 TaoToken 的 API 地址

Dify 自定义模型供应商,Base URL 填 TaoToken 的 API 地址

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 17:12:43 阅读更多 →
Kimi APIKey申请与CLI配置:智能体开发实战指南

Kimi APIKey申请与CLI配置:智能体开发实战指南

自打大模型API陆续开放以来,我一直在把各种各样的工作流往智能体上搬。Kimi这套APIKey申请与使用流程,我前前后后踩了不少坑,也总结出一套比较顺手的玩法。这篇文章就围绕Kimi大模型的APIKey申请、Kimi CLI命令行工具、智能体开发以及模型调用…

2026/9/19 17:11:43 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介:面向机器学习、深度学习与数据建模学习者的一份完整研究文献,聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本,系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程,展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型,在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志,发现loss从凌晨两点就开始往上爬,一路从0.8涨到1.35,整整六个小时没人发现。那六个小时的训练不仅白跑,还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud 🌤️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/19 3:59:36 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/19 3:53:08 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/19 4:02:43 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/15 21:39:18 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →