首页/新闻资讯/正文详情

Relay Client-Only Data(Client Schema Extensions)完全指南:在浏览器端扩展 GraphQL Schema 与本地数据建模

发布时间:2026/9/21 1:28:37 来源:云帆数科 栏目:资讯中心
Relay Client-Only Data(Client Schema Extensions)完全指南:在浏览器端扩展 GraphQL Schema 与本地数据建模
前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载本文聚焦 Relay 的 Client-Only Data客户端专属数据机制通过 Client Schema Extensions 在浏览器端扩展 GraphQL Schema为服务端数据补充小字段或完整建模仅存在于客户端的业务状态。读完本文你将掌握如何用extend type扩展既有类型、定义全新客户端类型、在 Fragment/Query 中读取这些字段并通过 Mutation/Subscription updater 与commitLocalUpdate等本地更新原语进行写入同时了解 Relay 编译器在底层如何处理这些.graphql扩展文件。为什么需要 Client-Only DataGraphQL 的 Schema 通常由服务端定义前端只能消费服务端暴露的字段。但在真实应用中存在大量“只属于客户端”的数据需求给服务端数据补充小信息例如给Comment类型临时加一个is_new_comment布尔字段用于在创建新评论后标记哪些评论是“新”的从而渲染不同的视觉样式这个字段不需要也不应该持久化到服务端。完整建模客户端状态例如请求的FetchStateFETCHED/PENDING/ERRORED、本地草稿、UI 临时状态等这些数据只存在于浏览器内存中由 Relay Store 统一管理。Relay 通过Client Schema Extensions提供了在客户端扩展 Schema 的能力让你可以修改服务端已有的类型为其添加新字段创建只存在于客户端、完全由 Relay Store 托管的新类型。所有这些字段和类型都遵循普通 GraphQL 的读写语义可以与服务端数据无缝混用。底层实现上Relay 编译器Rust 实现的 relay-compiler在构建 Schema 时会单独收集这些扩展文档再与服务端 SDL 合并具体可参见 build_schema.rs 中对扩展来源的读取逻辑。扩展既有类型Extending Existing Types为服务端类型添加客户端专属字段只需要在 Relay 编译器的--src源码目录下新增一个.graphql文件即可。该文件会被编译器当作“扩展文档”处理而不是覆盖服务端 Schema。extend type Comment { is_new_comment: Boolean }这段代码使用 GraphQL 标准的extend关键字扩展已有的Comment类型新增了一个is_new_comment: Boolean字段。之后你可以在组件中通过 fragments 或 queries 正常读取该字段并在需要时用标准 Relay API 更新它。典型的业务场景当用户创建一条新评论时在本地将其is_new_comment置为true从而在评论列表中给这条评论渲染不同的视觉处理这个标记无需服务端感知。从编译器视角看relay-compiler 在 build_schema.rs 中通过get_extension_sources收集项目自身的扩展文档并叠加base项目的扩展适用于多项目继承的配置随后调用parse_schema_with_extensions_parallel与relay_schema::build_schema_with_extensions_from_asts将服务端 Schema 与扩展合并为最终 Schema。同文件中的单元测试test_cached_server_asts_produce_same_schema直接以extend type Query { world: String }作为扩展 SDL 验证了“服务端 AST 扩展 AST 合并”的正确性——这正是“扩展既有类型”在编译器层面的工作方式。添加全新类型Adding New Types除了扩展既有类型你还可以在同一批.graphql文件中定义完全属于客户端的新类型语法与普通 GraphQL 完全一致# 单个文件中可以定义多个类型 enum FetchStatus { FETCHED PENDING ERRORED } type FetchState { # 可以用客户端类型组合出其他客户端类型 status: FetchStatus # 也可以引用常规的服务端类型 started_by: User! } extend type Item { # 可以用客户端专属类型扩展服务端类型 fetch_state: FetchState }这个示例展示了客户端 Schema 扩展的几个关键能力定义枚举与对象类型enum FetchStatus与type FetchState都是只存在于客户端的新类型类型之间自由组合FetchState可以引用同为客户端类型的FetchStatus可以引用服务端类型started_by: User!直接引用了服务端定义的User类型说明客户端类型与服务端类型可以在同一个类型系统中共存反向扩展通过extend type Item { fetch_state: FetchState }把客户端类型作为字段挂到服务端类型Item上让查询时可以一路取到客户端状态。需要说明的是原文档中提及的html/js/relay/schema/是 Meta 内部代码库路径在开源OSS使用方式下这些.graphql文件放在你配置给编译器的源码目录--src中即可编译器会自动扫描并识别其中的extend文档。项目的多项目配置示例可参考 compiler/test-project/relay.config.json其中projects.name.schema指向服务端 Schema 文件扩展文档则来自各项目的源码目录。读取 Client-Only Data读取客户端专属数据与读取普通字段没有区别——直接在 Fragment 或 Query 中正常选取即可const data useFragment( graphql fragment CommentComponent_comment on Comment { # 客户端专属字段可以像其他字段一样被选取 is_new_comment body { text } } , props.user, );关键点is_new_comment虽然是客户端扩展字段但在 Fragment 中的选取语法与body { text }这类服务端字段完全一致编译器在构建时知道它的来源是客户端扩展由于它存储在 Relay Store 中组件会像订阅普通字段一样订阅它——当该字段被本地更新后使用该 Fragment 的组件会自动重渲染读取客户端数据的前提是数据确实存在于 Store 中。对于新建的本地记录你需要先通过本地数据更新将其写入 Store。更新 Client-Only Data更新客户端专属数据有两条标准路径一是借助服务端操作的 updater 函数二是使用专门做本地更新的原语。无论哪种方式任何本地更新都会自动通知订阅该数据的组件并触发重渲染。在 Mutation / Subscription updater 中更新在 mutation 或 subscription 的 updater 函数中你可以正常读写客户端字段——例如在创建评论的 Mutation 完成后把新产生的 Comment 记录的is_new_comment置为true。使用本地更新原语不依赖任何服务端操作时Relay 提供了两个核心本地更新 API详见 local-data-updates.mdcommitLocalUpdate(environment, updater)接收一个 Environment 和 updater 函数updater 拿到RecordSourceSelectorProxy类型的store参数可以命令式地在 Store 中创建新记录、更新或删除既有记录const {commitLocalUpdate, graphql} require(react-relay); function commitCommentCreateLocally(environment, feedbackID) { return commitLocalUpdate(environment, store { const feedbackRecord store.get(feedbackID); const connectionRecord ConnectionHandler.getConnection( feedbackRecord, CommentsComponent_comments_connection, ); // 从零开始创建一条本地 Comment 记录 const id client:new_comment:${randomID()}; const newCommentRecord store.create(id, Comment); // ... 写入新评论的内容可包含 is_new_comment 等客户端字段 // 从零开始创建一条新的 Edge 并插入连接末尾 const newEdge ConnectionHandler.createEdge( store, connectionRecord, newCommentRecord, CommentEdge /* Edge 的 GraphQL 类型 */, ); ConnectionHandler.insertEdgeAfter(connectionRecord, newEdge); }); }注意这里使用的记录 ID 形如client:new_comment:id这正是客户端数据的典型标识方式——这类记录只存在于本地 Store不会发送给服务端。关于连接Connection上插入/删除的更多细节可参考 updating-connections.md。该 API 在运行时的实现位于 commitLocalUpdate.js其签名即(environment: IEnvironment, updater: StoreUpdater) void。environment.commitPayload(operation, payload)接收一个OperationDescriptor和查询的 payload将其像普通服务端查询响应一样写入 Storepayload 可通过在查询上添加raw_response_type指令获得类型化的 Flow 类型const {createOperationDescriptor} require(relay-runtime); const operationDescriptor createOperationDescriptor(FooQuery, { id: an-id, otherVariable: value, }); const payload: FooQueryRawResponse {...}; environment.commitPayload(operationDescriptor, payload);createOperationDescriptor由relay-runtime导出接收查询与查询变量payload 中即可包含客户端字段用于一次性灌入一组本地数据例如模拟一次本地查询结果。实践要点与最佳实践综合原文档与仓库实现使用 Client-Only Data 时建议遵循以下原则明确职责边界客户端 Schema 扩展只用于“仅客户端需要、无需服务端持久化”的数据UI 状态、本地标记、草稿、加载/错误状态等需要跨端共享或有持久化诉求的数据仍应走服务端 Schema。利用类型系统为客户端状态定义清晰的enum与type并允许客户端类型与服务端类型互相引用让查询与 Fragment 的编写体验与纯服务端数据完全一致。善用本地更新原语纯本地变更优先使用commitLocalUpdate需要以查询响应的形式灌入整块数据时使用commitPayload与服务端操作联动时在 Mutation/Subscription updater 中一并更新客户端字段。理解底层合并机制编译器把扩展文档与服务端 SDL 分开解析再合并build_schema.rs因此扩展文件中的语法错误会在编译期被单独定位与报告不会污染服务端 Schema 定义。总结Client-Only Data 是 Relay 在纯客户端场景下最重要的数据建模能力之一通过extend type为服务端类型补充轻量字段或定义全新的客户端类型再借助 Fragment/Query 统一读取并用 Mutation/Subscription updater、commitLocalUpdate与commitPayload统一更新。这套机制让“服务端数据 客户端状态”在 Relay Store 中共存且遵循同一套读写语义组件订阅与自动重渲染也天然适用。配合 relay-compiler 对扩展文档的合并处理与测试保障它是构建复杂交互型 React 应用时不可或缺的工具。赞分享前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载相关推荐Apollo Client SchemaLink 全解析在本地 GraphQL Schema 上执行查询实现 SSR 与数据 MockingApollo Client SchemaLink 全解析在本地 GraphQL Schema 上执行查询实现 SSR 与数据 Mocking SchemaL前端GraphQL在浏览器中运行 Eleventy11ty/client 浏览器端构建包完全指南在浏览器中运行 Eleventy 11ty/client 浏览器端构建包完全指南 导读 11ty/client 是 EleventyBuild Awes前端开发工具在 Meteor 中集成 Apollo 与 GraphQL从零搭建 Schema、Resolver、Server 与 Client 的完整指南在 Meteor 中集成 Apollo 与 GraphQL从零搭建 Schema、Resolver、Server 与 Client 的完整指南 本指南以 Me后端前端开发工具移动开发上一篇从0到1部署gemma-4-e2b-it-5bit本地API服务构建私有多模态AI应用实战下一篇TGIK Windows容器完全指南在Kubernetes中运行Windows工作负载的终极教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

MATLAB实现SBM与超效率SBM模型:DEA效率评价完整指南
MATLAB实现SBM与超效率SBM模型:DEA效率评价完整指南

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

在 Egg 项目中使用 Sequelize ORM 实现 MySQL 数据层管理
在 Egg 项目中使用 Sequelize ORM 实现 MySQL 数据层管理

后端Web框架 【免费下载链接】egg 🥚🥚🥚🥚 Born to build better enterprise frameworks and apps with Node.js & Koa. https://307.run/eggcode 项目地址: https://gitcode.com/gh_mirrors/eg/egg 点击查看 免费… · 2026/9/21 1:28:37

机器人实时系统实战:从PREEMPT_RT到ROS2低抖动架构
机器人实时系统实战:从PREEMPT_RT到ROS2低抖动架构

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

外贸建站用什么平台好?避开3大坑,这4点注意事项最保命
外贸建站用什么平台好?避开3大坑,这4点注意事项最保命

外贸建站用什么平台好?避开3大坑,这4点注意事项最保命 找建站公司怕被坑高价?别急,先看清这3个注意事项再掏钱。 很多老板在华北圈子里转了一圈,发现报价从几千到几十万都有,心里直打鼓:到底哪个才靠谱?怕交钱后网站慢得像蜗牛,更怕上线没半年就出安全漏洞。 其实, 外贸建站用什么平台好… · 2026/9/21 9:46:33

一个服务器上有两个网站要备案两次吗速查手册
一个服务器上有两个网站要备案两次吗速查手册

一个服务器上有两个网站要备案两次吗速查手册 改个需求建站公司拖一周,这种憋屈事儿我见得太多了。作为湖北创业团队的负责人,我最怕的就是因为搞不清技术细节,让外包团队有借口拖延进度。其实,很多所谓的“技术难题”,往往只是信息不对称造成的误解。今天我就把这份关于 一个服务器上有两个网站要备案两次吗 的… · 2026/9/21 9:32:45

单位网络建设的设计方案全流程解析避坑指南
单位网络建设的设计方案全流程解析避坑指南

单位网络建设的设计方案全流程解析避坑指南 改个需求建站公司拖一周,这种痛谁懂?很多单位搞网络建设,前期方案写得漂漂亮亮,后期落地全是坑。别急着怪供应商,大概率是你们的【单位网络建设的设计方案】里,把【完整流程】搞丢了,或者干脆没搞。… · 2026/9/21 9:17:55

3个实战案例教你挑对软件下载网站哪个好防挂马
3个实战案例教你挑对软件下载网站哪个好防挂马

3个实战案例教你挑对软件下载网站哪个好防挂马 上周帮客户复盘,发现官网弹窗全是博彩广告,后台日志被清空,这种被黑挂马的恐惧,很多站长都经历过。 别慌,选对底层架构的下载站,比事后打补丁重要十倍。 结合3个被黑过的实战案例,我拆解一下“软件下载网站哪个好”的评判标准。 设计原则与信任感构建… · 2026/9/21 9:02:23

网站标识代码怎么加实操详解及对比评测避坑指南
网站标识代码怎么加实操详解及对比评测避坑指南

网站标识代码怎么加实操详解及对比评测避坑指南 备案流程一头雾水,是很多中小企业在上线官网时最容易卡壳的环节。很多老板以为只要把网站做出来,挂上域名就能收流量,结果发现没ICP备案根本打不开,或者加了备案代码位置不对导致审核不通过。这时候,一份清晰的网站标识代码怎么加的操作指南,加上不同服务商方案的对… · 2026/9/21 8:45:49

别被网页制作模板中文坑了,懂建站报价才不亏
别被网页制作模板中文坑了,懂建站报价才不亏

别被网页制作模板中文坑了,懂建站报价才不亏 网站做好了没人访问,这钱白花得冤不冤?很多老板找外包,问完建站报价,对方甩给你一个“网页制作模板中文”链接,说这是高端定制。你一看,哦,是套壳的。更坑的是,有些模板连基础的SEO结构都没做好,上线三个月,百度搜不到你公司名字。… · 2026/9/21 8:31:34

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化
Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡… · 2026/9/21 0:02:39

Word表格编号全攻略:从列表编号到题注交叉引用
Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技… · 2026/9/21 0:02:39

从第一个站到第二个站:独立开发者的静态网站选型与落地实践
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&… · 2026/9/20 0:00:41

Claude Code 按智谱AI指南装完,ANTHROPIC_BASE_URL 改走 TaoToken 兼容通道行不行
Claude Code 按智谱AI指南装完,ANTHROPIC_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/21 0:00:18

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程
agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and … · 2026/9/21 0:00:18

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,… · 2026/9/21 0:00:18

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码