Relay 网络层(Network Layer)完全指南:从 Network.create 到自定义传输、缓存与订阅

发布时间:2026/9/23 15:14:15

Relay 网络层(Network Layer)完全指南:从 Network.create 到自定义传输、缓存与订阅 前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载本文是 Relay v19 官方文档 network-layer.md 的深入解读。核心主题是Relay 如何通过实现INetwork接口的对象即网络层与任意 GraphQL 服务通信以及如何使用relay-runtime提供的Network.create快速搭建、并如何扩展出网络级缓存、遥测、文件上传与订阅支持。读完本文你将掌握在 Relay 应用中从零构建网络层、按需定制传输与认证、并利用仓库源码理解其内部执行链路的完整能力。为什么需要网络层Environment 与 GraphQL 服务的解耦在 Relay 的运行时架构中Environment是核心枢纽——它负责向你的 GraphQL 服务器发起请求同时持有 Relay 的归一化数据缓存Store。但 Relay 本身不绑定任何具体的网络传输方式无论是 HTTP、WebSocket还是自定义的 RPC只要开发者提供一个满足INetwork接口的对象Environment就能借助这个网络层去执行查询query、变更mutation以及如果服务器支持订阅subscription。这种设计带来的直接收益是解耦应用的认证方式、请求头、超时策略、传输协议等网络细节都被收敛到网络层内部Environment与运行时的其余部分完全不关心这些细节。正如官方文档所述This allows developers to use whatever transport (HTTP, WebSockets, etc) and authentication is most appropriate for their application, decoupling the environment from the particulars of each applications network configuration.从源码看INetwork接口极其精简只要求一个execute方法见 RelayNetworkTypes.jsexport interface INetwork { readonly execute: ExecuteFunction; }而ExecuteFunction接收请求参数、变量、缓存配置等返回一个可观察对象RelayObservableGraphQLResponse见 RelayNetworkTypes.jsexport type ExecuteFunction ( request: RequestParameters, variables: Variables, cacheConfig: CacheConfig, uploadables?: ?UploadableMap, logRequestInfo?: ?LogRequestInfoFunction, ... ) RelayObservableGraphQLResponse;你可以在 RelayNetworkTypes.js 中查看这些类型FetchFunction、SubscribeFunction、GraphQLResponse等的完整定义。快速开始用Network.create构建最小网络层目前创建网络层最简便的方式是使用relay-runtime包提供的Network.create帮助函数。官方文档给出了一个可直接运行的最小示例network-layer.mdimport { Environment, Network, RecordSource, Store, } from relay-runtime; // Define a function that fetches the results of an operation (query/mutation/etc) // and returns its results as a Promise: function fetchQuery( operation, variables, cacheConfig, uploadables, ) { return fetch(/graphql, { method: POST, headers: { // Add authentication and other headers here content-type: application/json }, body: JSON.stringify({ query: operation.text, // GraphQL text from input variables, }), }).then(response { return response.json(); }); } // Create a network layer from the fetch function const network Network.create(fetchQuery); const store new Store(new RecordSource()) const environment new Environment({ network, store // ... other options }); export default environment;逐个参数拆解fetchQuery函数上述fetchQuery就是FetchFunction的具体实现其四个核心参数的含义如下类型签名见 RelayNetworkTypes.js参数类型说明operationRequestParameters本次操作的元数据包含operation.text编译后的 GraphQL 文本、name、operationKindquery/mutation/subscription、id持久化查询 ID等variablesVariables本次操作对应的变量对象需随请求体发送给服务器cacheConfigCacheConfig缓存相关配置如force是否强制绕过缓存、poll轮询间隔单位毫秒uploadables?UploadableMap可上传的文件/Blob 映射File | Blob仅在 mutation 需要文件上传时使用其中operation.text正是把编译后的 GraphQL 文本发往服务器的关键——Relay 编译器在构建阶段会把graphql标签中的查询编译成可执行文本网络层只需原样透传即可。创建 Environment 与导出Network.create(fetchQuery)返回一个实现了INetwork接口的对象随后把它与Store一起注入Environment。这里的Store是 Relay 的归一化数据缓存配合RecordSource使用。relay-runtime的入口文件会统一导出这些 APIindex.jsEnvironment: RelayModernEnvironment, Network: RelayNetwork, QueryResponseCache: RelayQueryResponseCache,注意官方文档特别提醒network-layer.md上面只是帮助入门的基础示例。stream、defer指令以及持久化查询Persisted Queries等特性需要在你的fetchQuery函数中补充额外的逻辑。例如defer/stream会产生分块incremental响应需要把增量 payload 逐步传给 Relay持久化查询则通常改为发送operation.id文本 ID而非完整文本。相关实操可继续阅读 持久化查询指南。网络层内部如何工作从fetch函数到RelayObservable理解了使用方式后值得深入Network.create的源码实现看它内部到底做了什么。实现位于 RelayNetwork.jsfunction create( fetchFn: FetchFunction, subscribe?: SubscribeFunction, ): INetwork { // Convert to functions that returns RelayObservable. const observeFetch convertFetch(fetchFn); const providerValueCache: Map() unknown, unknown new Map(); function execute( request: RequestParameters, variables: Variables, cacheConfig: CacheConfig, uploadables?: ?UploadableMap, logRequestInfo: ?LogRequestInfoFunction, ): RelayObservableGraphQLResponse { const operationVariables withProvidedVariables( variables, request.providedVariables, providerValueCache, ); if (request.operationKind subscription) { invariant( subscribe, RelayNetwork: This network layer does not support Subscriptions. To use Subscriptions, provide a custom network layer., ); invariant( !uploadables, RelayNetwork: Cannot provide uploadables while subscribing., ); return subscribe(request, operationVariables, cacheConfig); } const pollInterval cacheConfig.poll; if (pollInterval ! null) { invariant( !uploadables, RelayNetwork: Cannot provide uploadables while polling., ); return observeFetch(request, operationVariables, {force: true}).poll( pollInterval, ); } return observeFetch( request, operationVariables, cacheConfig, uploadables, logRequestInfo, ); } return {execute}; }这里可以提炼出三个关键设计返回值统一为RelayObservable你传入的fetchFn返回 Promise 或直接抛错convertFetch会把它包装成RelayObservableConvertToExecuteFunction.js。特殊地如果fetchFn直接返回一个Error实例会被显式转换为一个立即报错的 observable从而让下游统一以流的方式处理成功与失败。订阅走独立的subscribe分支当operationKind subscription时execute会转而调用创建网络层时传入的第二个参数subscribe。如果没有提供subscribe会抛出明确的 invariant 错误This network layer does not support Subscriptions。同时订阅与文件上传uploadables互斥。轮询polling由网络层内置当cacheConfig.poll不为空时execute会以{force: true}强制发请求并用.poll(pollInterval)按给定间隔重复执行。另外withProvidedVariables会解析编译期标记的 provided variables类似__relay_internal__pv__前缀的变量并使用providerValueCache缓存 provider 的返回值。对应的测试用例在 RelayNetwork-test.js 中验证了同一网络层内 provider 的取值在首次execute后会被复用这一行为。进阶用法一网络级缓存与QueryResponseCache网络层是放置网络级缓存的理想位置——它位于 Relay Store归一化缓存之下、真实服务器之上。官方文档明确指出network-layer.mdThe network layer provides a place for developers to customize the data fetching behaviors. For example, adding network level caching, telemetry or support for uploading form data for mutations.relay-runtime为此内置了一个开箱即用的网络级缓存RelayQueryResponseCache由入口文件以QueryResponseCache之名导出见 index.js。其核心实现位于 RelayQueryResponseCache.js特点包括TTL 过期构造时传入{size, ttl}get()时会遍历清理已过期的条目fetchTime ttl Date.now()才视为有效。容量上限与淘汰策略当条目数超过size时按最近最少更新least-recently updated的顺序淘汰——利用Map的插入序特性删除最旧的 key。命中时注入缓存时间戳返回的 payload 会在extensions.cacheTimestamp中带上命中时刻的fetchTime方便上层感知数据新鲜度。缓存键由JSON.stringify(stableCopy({queryID, variables}))生成保证变量顺序无关的稳定键RelayQueryResponseCache.js。典型用法是在fetchQuery内部先查缓存、再决定是否发请求import {QueryResponseCache} from relay-runtime; const responseCache new QueryResponseCache({ size: 250, // 最大缓存条数 ttl: 15 * 60 * 1000, // 15 分钟有效期 }); function fetchQuery(operation, variables, cacheConfig) { const {id, text} operation; const isQuery operation.operationKind query; const forceFetch cacheConfig cacheConfig.force; // 命中缓存且未被强制刷新时直接返回缓存 if (isQuery !forceFetch) { const cached responseCache.get(id ?? text, variables); if (cached ! null) { return cached; } } return fetch(/graphql, { method: POST, headers: {content-type: application/json}, body: JSON.stringify({query: text, variables}), }).then(response response.json()).then(json { // 仅缓存纯查询结果 if (isQuery json) { responseCache.set(id ?? text, variables, json); } return json; }); }注意与fetchQueryfetchQuery.js配合时Relay 默认会向网络层传递cacheConfig.force true来绕过这类网络级缓存——这正是强制走网络语义的实现方式。进阶用法二遥测Telemetry官方文档将telemetry列为网络层可定制的典型能力之一。实现上可以从两个层面接入网络层内部埋点在fetchQuery中自行记录请求开始/结束/失败的时间与耗时这是最简单直接的方式。利用logRequestInfo参数ExecuteFunction的第五个参数logRequestInfo见 RelayNetworkTypes.js会在请求执行时被传入网络层。更完整的遥测体系则是Environment的log配置项——从源码看RelayModernEnvironment在构造时会用wrapNetworkWithLogObserver包裹传入的网络层RelayModernEnvironment.js从而在网络请求的生命周期节点自动产生日志事件统一进入log回调。EnvironmentConfig中network是必填项而log、store等为可选项RelayModernEnvironment.js。进阶用法三为 Mutation 上传文件Uploadables网络层还承担了** mutation 表单数据上传**的职责。当你在 Relay 中通过commitMutation的uploadables选项传入文件映射时类型为UploadableMap {readonly [key: string]: File | Blob}见 RelayNetworkTypes.js该映射会一路传递到网络层的fetchQuery(operation, variables, cacheConfig, uploadables)的第四个参数。此时你的fetchQuery需要检测uploadables若存在则改用FormDatamultipart/form-data而非 JSON 发送请求例如function fetchQuery(operation, variables, cacheConfig, uploadables) { if (uploadables ! null) { const formData new FormData(); formData.append(query, operation.text); formData.append(variables, JSON.stringify(variables)); Object.keys(uploadables).forEach(key { formData.append(key, uploadables[key]); }); return fetch(/graphql, {method: POST, body: formData}) .then(response response.json()); } // ... 普通 JSON 请求分支 }支持订阅Subscriptions提供subscribe函数如果你的 GraphQL 服务器支持订阅通常基于 WebSocket请给Network.create传入第二个参数subscribe。其类型为SubscribeFunction见 RelayNetworkTypes.js接收request、variables、cacheConfig三个参数并返回一个随服务器推送多次数据的RelayObservableGraphQLResponseconst network Network.create(fetchQuery, subscribeFunction);其中subscribeFunction通常基于RelayObservable.create封装 WebSocket 连接将收到的每次推送next给下游。如前述源码所示RelayNetwork.jsexecute会对operationKind subscription的请求走subscribe分支若未提供该函数则会立即抛出明确错误提示你需要自定义网络层。进阶用法四自定义认证与请求头fetchQuery函数内的headers就是你接入认证的最佳位置。官方文档在示例中留了注释 Add authentication and other headers here。你可以在请求头中加入Authorization、CSRF token、自定义 trace ID 等function fetchQuery(operation, variables) { return fetch(/graphql, { method: POST, headers: { content-type: application/json, authorization: Bearer ${getAccessToken()}, x-trace-id: generateTraceId(), }, body: JSON.stringify({query: operation.text, variables}), }).then(response response.json()); }由于fetchQuery是普通 JavaScript 函数认证令牌的获取方式localStorage、cookie、内存变量等完全由你决定Relay 不施加任何约束。常见问题与调试建议提示 This network layer does not support Subscriptions表示你调用了订阅相关的 API但Network.create未传入subscribe参数。按上文支持订阅一节补齐即可RelayNetwork.js。想强制绕过网络级缓存使用fetchQuery(environment, query, variables)时默认fetchPolicy为network-only且会向网络层传cacheConfig.force truefetchQuery.js如需命中 Store 再决定是否走网络可改为store-or-networkfetchQuery.js。请求被意外合并/去重fetchQuery会对相同环境、查询、变量的在途请求做去重fetchQuery.js这是预期行为而非网络层故障。调试网络请求除了浏览器 DevTools可借助logRequestInfo与Environment的log配置输出请求生命周期事件生产环境建议接入集中式遥测平台。小结网络层是 Relay 与你的 GraphQL 服务之间唯一的 I/O 通道。通过Network.create(fetchQuery, subscribe)你可以在十几行代码内建立可运行的最小实现而借助 RelayNetwork.js 的源码理解其统一为RelayObservable、订阅分支、轮询分支、provided variables的执行模型后你便可以在网络层内自由叠加网络级缓存QueryResponseCache、遥测、文件上传与自定义认证从而在完全不改动运行时其他部分的前提下把网络行为完全定制为你应用所需的样子。若想进一步了解Environment的其余配置项如missingFieldHandlers、getDataID、relayFieldLogger可继续阅读 Relay Environment 参考文档。赞分享前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载相关推荐Relay 网络层Network Layer完全指南从 Network.create 到自定义传输与缓存策略Relay 网络层Network Layer完全指南从 Network.create 到自定义传输与缓存策略 Relay 将「数据请求如何发出」与「数据如前端开发工具Relay 网络层Network Layer完全指南自定义 Network、请求缓存与订阅传输Relay 网络层Network Layer完全指南自定义 Network、请求缓存与订阅传输 Relay 通过网络层Network Layer这一抽前端开发工具Relay 网络层Network Layer完全指南从 INetwork 接口到自定义 fetch 与响应缓存Relay 网络层Network Layer完全指南从 INetwork 接口到自定义 fetch 与响应缓存 Relay 通过 INetwork 接口把前端开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/23 16:19:28

OpenSpec 规格优先实践:从接口契约到自动化校验的落地指南

1. 从“规格”说起:OpenSpec 到底在解决什么问题第一次听到 OpenSpec 这个名字,很多人会下意识地把它和 OpenAPI、JSON Schema 归到一类,觉得“又是一个写接口文档的规范”。我一开始也是这么想的,直到真正在一个多人协作的中型项…

2026/9/23 16:19:28

AutoJs 4.1.0 Android自动化脚本入门:无障碍服务与控件选择器实战

我第一次听说“clsq客户端”这个名字时,第一反应是某个内部工具,后来被朋友拉到一起折腾才发现,它背后真正有价值的东西其实是基于AutoJs 4.1.0的一套Android自动化脚本方案。AutoJs这个工具在国内Android圈子里名声很大,它是一个…

2026/9/23 16:19:28

AIoT边缘计算网关怎么选?从场景出发,找到最匹配的那一款

选型之前,先别急着看参数很多人选边缘计算网关,第一反应是打开规格书,比CPU核心数、比NPU算力、比接口数量。比着比着就乱了——这个型号算力高但串口少,那个型号串口多但没NPU,还有一个什么都好但价格超预算。正确的顺…

2026/9/23 16:14:27

LM358音频放大电路设计与调试避坑指南

简介:本资源是一份面向电子电路设计初学者与硬件开发者的LM358双运放音频应用实践资料包,聚焦单电源条件下音频信号放大、传感检测与简易报警系统构建等典型场景。内含7款经验证的LM358音频放大电路图(含高灵敏度声音探听器、麦克风前置放大器…

2026/9/23 12:07:00

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/23 12:06:55

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/23 0:01:54

3个实战技巧搞定形式英语:从看教程到跑通性能优化

3个实战技巧搞定形式英语:从看教程到跑通性能优化 看了一堆教程还是不会写项目?别慌,这种“眼高手低”的困境在开发者圈子里太常见了。很多人以为卡点在语法,其实真正拦路虎是缺乏将知识点串联成完整链路的能力。今天咱们不聊虚的,直接拿【形式英语】这…

2026/9/22 16:34:32

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/22 20:01:30

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/22 13:25:41

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码