前端开发工具【免费下载链接】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),仅供参考
企业数字化 ERP 产品动态
相关推荐
TekLynx实战:3个高频面试题拆解,告别只会语法不会搭项目 TekLynx实战:3个高频面试题拆解,告别只会语法不会搭项目 刚学完Python或Java基础语法,打开IDEA或PyCharm,脑子一片空白?别慌,这是90%初学者都会遇到的“语法孤岛”现象。你背下了 for… · 2026/9/23 15:14:22
气动搬运机械手PLC控制设计与实机联调指南 简介:本资源是一份完整的本科毕业设计论文,面向自动化、机电一体化及控制工程等专业的高年级本科生与毕设指导教师,聚焦气动搬运机械手的PLC控制系统开发与工程实现。论文以河南理工大学本科毕设为背景,系统涵盖三自由度气动机械手… · 2026/9/23 15:14:22
五子棋AI源码拆解:C++/Qt + Alpha-Beta剪枝实战 简介:基于C与Qt实现的五子棋博弈游戏完整项目,核心采用极大极小搜索与Alpha-Beta剪枝算法,并附带设计报告。适合高校人工智能、计算机、自动化等专业学生用于课程设计或毕业设计,也适合对棋类AI感兴趣的开发者学习博弈树搜索与界面… · 2026/9/23 15:14:14
显示器对比面试必问:3个核心指标拆解底层渲染原理 显示器对比面试必问:3个核心指标拆解底层渲染原理 看了一堆教程还是不会写项目?别急,先看看你电脑屏幕是不是在“骗”你。很多转行做前端或图形开发的伙伴,面试时被问到【显示器对比】,往往只能答出分辨率和刷新率,一旦深入问到色彩空间映射或子像素渲… · 2026/9/23 15:56:33
深信服智慧校园云机房部署指南:aDesk桌面云与超融合实战 简介:这份PPT资源面向学校信息化管理者、机房运维人员及教育行业方案设计者,系统讲解如何用桌面云替代传统PC机房,解决软硬件升级困难、故障率高、课程切换繁琐等痛点。内容围绕教师、学生、管理员三类角色展开:教师可移动备课、一… · 2026/9/23 15:56:33
欧盟车牌识别实战:534张VOC数据转YOLO格式训练全流程 简介:534张欧盟车牌图像数据集面向车牌检测与OCR字符识别任务,适合计算机视觉初学者、算法工程师及自动驾驶研发人员用于模型训练、算法验证与数据集制作流程练习。压缩包共1070个文件,包含534张jpg原图与一一对应的534个xml标注文件… · 2026/9/23 15:56:33
如何把视频变小避坑指南:3招搞定体积压缩 如何把视频变小避坑指南:3招搞定体积压缩 很多后端或全栈工程师在开发时都遇到过这种尴尬:代码逻辑跑通了,单元测试也全绿,结果一部署到测试环境,前端上传视频直接报错“文件过大”。你翻遍文档,发现服务器 Nginx 配置里… · 2026/9/23 15:56:33
隐式扩散重新模糊增强源码解析:从条件生成到扩散采样实战 简介:本资源面向计算机相关专业的毕业设计、期末大作业与课程实训场景,提供一套基于隐式扩散的重新模糊增强方法完整Python实现,帮助学习者理解扩散模型在图像去模糊与质量增强中的落地方式。压缩包共96个文件,约60.2MB࿰… · 2026/9/23 15:56:26
揭秘游戏软件开发公司底层优化:手写实现让帧率翻倍 揭秘游戏软件开发公司底层优化:手写实现让帧率翻倍 看了一堆教程还是不会写项目?这大概是很多刚入行或者想进阶的开发者的痛点。视频里跑得飞起,自己上手就卡壳,尤其是面对大型商业项目时,那种无力感特别强。很多培训机构教你“怎么调用库”,但很少教你… · 2026/9/23 15:56:01
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29