graphql-yoga:基于 Envelop 与 Socket.IO 实现 GraphQL 实时通信通道示例详解
后端API设计【免费下载链接】graphql-yoga Rewrite of a fully-featured GraphQL Server with focus on easy setup, performance great developer experience. The core of Yoga implements WHATWG Fetch API and can run/deploy on any JS environment.项目地址https://gitcode.com/gh_mirrors/gr/graphql-yoga点击查看免费下载本篇以 graphql-yoga 仓库中 examples/envelop/graphql-socket.io 示例为核心讲解如何在不使用 Yoga HTTP 入口的情况下把envelop/core的插件化执行管线parse/validate/execute/subscribe 插件体系接入一个既有的 Socket.IO 服务器从而获得 GraphQL 的实时/长连接执行能力。读完本文你能完整复现该示例的运行流程并理解 Envelop 的envelop()工厂如何为每个操作operation按需产出执行函数以及useSchema、useLogger两个插件在管线中的具体挂载点。示例定位与运行方式该示例的主题是用 Envelop 实现 GraphQL 流程并借助n1ru4l/socket-io-graphql-server库为现有 Socket.IO 服务器增强 GraphQL 能力。它属于examples/envelop/目录下一组“Envelop 跨传输层集成”示例之一同目录还有 apollo-server、graphql-ws、graphql-sse、graphql-socket.io 等专门演示 Envelop 作为执行编排核心、传输协议可插拔的设计。README 给出的运行步骤完整如下可直接照做在仓库根目录安装全部依赖使用pnpmcd进入examples/envelop/graphql-socket.io目录运行pnpm run start运行pnpm run test:client对服务器执行一次测试操作。对照 package.json 中的 scripts 定义这两条命令的实际含义是scripts: { start: ts-node index.ts, // 直接以 ts-node 启动服务端 test:client: ts-node test-client.ts // 直接以 ts-node 启动客户端 }即无需任何编译步骤ts-node直接解释执行 TypeScript 源文件。服务端依赖中的关键版本以当前仓库为准socket.io4.8.3、socket.io-client4.8.3、n1ru4l/socket-io-graphql-server与n1ru4l/socket-io-graphql-client均为 0.13.0、graphql17.0.2、graphql-tools/schema10.0.31其中envelop/core使用*表示走本仓库 workspace 内源码package.json 中engines要求 Node18.0.0运行本示例的最低环境即由此确定。服务端实现逐段解析完整的服务器代码见 index.ts共 55 行可以分成四个环节import * as http from http; import { execute, parse, subscribe, validate } from graphql; import { Server } from socket.io; import { envelop, useLogger, useSchema } from envelop/core; import { makeExecutableSchema } from graphql-tools/schema; import { registerSocketIOGraphQLServer } from n1ru4l/socket-io-graphql-server; // 1. 定义可执行 schema const schema makeExecutableSchema({ typeDefs: /* GraphQL */ type Query { hello: String! } , resolvers: { Query: { hello: () World, }, }, }); // 2. 创建 Envelop 执行管线 const getEnveloped envelop({ parse, validate, execute, subscribe, plugins: [useSchema(schema), useLogger()], }); // 3. 创建 HTTP Socket.IO 服务器 const httpServer http.createServer(); const socketServer new Server(httpServer); // 4. 将 GraphQL 能力注册到 Socket.IO 服务器 registerSocketIOGraphQLServer({ socketServer, getParameter: async ({ socket, graphQLPayload }) { const { schema, contextFactory, parse, validate, execute, subscribe } getEnveloped({ socket, graphQLPayload, }); return { parse, validate, execute, subscribe, graphQLExecutionParameter: { schema, contextValue: await contextFactory(), }, }; }, }); httpServer.listen(3000, () { // eslint-disable-next-line no-console console.log(Listening on http://localhost:3000); });schema 与 Envelop 管线的组装schema 由graphql-tools/schema的makeExecutableSchema构造包含一个最简Query.hello字段。envelop()工厂接收parse/validate/execute/subscribe四个 graphql-js 基础函数作为管线默认实现以及plugins数组返回一个getEnveloped函数。从源码看create.tsenvelop()内部先创建 orchestrator 对插件做编排随后返回的getEnveloped(context)在每次调用时以传入的初始 context 为种子产出一组被 instrumentation 包裹的执行函数return { parse: instrumented.fn(instrumentation?.parse, typedOrchestrator.parse(context)), validate: instrumented.fn(instrumentation?.validate, typedOrchestrator.validate(context)), contextFactory: instrumented.fn(instrumentation?.context, typedOrchestrator.contextFactory(context as any)), execute: instrumented.asyncFn(instrumentation?.execute, typedOrchestrator.execute), subscribe: instrumented.asyncFn(instrumentation?.subscribe, typedOrchestrator.subscribe), schema: typedOrchestrator.getCurrentSchema(), };这解释了示例中getEnveloped({ socket, graphQLPayload })的写法每次收到一个 GraphQL 操作都调用一次getEnveloped并带上操作特有的信息Socket.IO 的socket对象与原始graphQLPayload作为初始 context得到该操作私有的parse/validate/execute/subscribe与schema。context 的初始化即从这里开始——这正是把“连接级信息”如 socket带入执行上下文的入口点。两个插件的挂载点plugins: [useSchema(schema), useLogger()]分别做两件事均可在 packages/envelop/core/src/plugins 下核对实现useSchema(schema)use-schema.ts在onPluginInit钩子中调用setSchema(schema)把 schema 注入编排器使getEnveloped()返回的schema字段orchestrator 的getCurrentSchema()以及后续解析、校验都能拿到同一份 schema。useLogger()use-logger.ts挂在onExecute/onSubscribe钩子上执行时输出execute-start/execute-end订阅时输出subscribe-start/subscribe-end含args与结果result。它支持skipIntrospection选项为 true 时在onParse阶段检测 introspection 操作并跳过日志。因此运行test:client时服务端终端会打印出本次查询的执行出入参——这也是验证“操作确实走过了 Envelop 管线”的直观证据。getParameterEnvelop 与 Socket.IO 协议的交接点registerSocketIOGraphQLServer是外部库n1ru4l/socket-io-graphql-server提供的注册函数其核心入参是getParameter回调每当 Socket.IO 客户端发起一次 GraphQL 操作该回调就会收到{ socket, graphQLPayload }并需要返回parse/validate/execute/subscribe由getEnveloped(...)产出的、经过全部插件增强的执行函数graphQLExecutionParameter包含schema与contextValue: await contextFactory()——注意contextFactory()是异步函数这里await其结果得到完整的执行上下文值。从示例结构可以看出 Envelop 的通用集成模式传输层Socket.IO只负责协议的收发与生命周期Envelop 负责把一次操作转化为“解析 → 校验 → 执行/订阅”的可编排管线getParameter就是二者的交接点任何能在该回调中拿到请求/操作信息的传输层都可以按同样方式接入。客户端测试脚本pnpm run test:client执行的 test-client.ts 完整代码如下import { io } from socket.io-client; import { createSocketIOGraphQLClient } from n1ru4l/socket-io-graphql-client; const socket io(http://localhost:3000); const client createSocketIOGraphQLClient(socket); socket.on(connect, async () { const execution client.execute({ operation: /* GraphQL */ query { hello } , }); for await (const result of execution) { // eslint-disable-next-line no-console console.log(JSON.stringify(result)); } client.destroy(); socket.close(); });其流程为用socket.io-client连接http://localhost:3000即服务端httpServer.listen(3000)的端口→ 用createSocketIOGraphQLClient(socket)把该 socket 包装为 GraphQL 客户端 → 在connect事件中调用client.execute({ operation })发起query { hello }查询 →client.execute返回一个可异步迭代的执行流用for await...of逐条消费结果该写法同样兼容订阅类操作的多帧结果→ 结束后client.destroy()与socket.close()释放连接。成功运行后客户端终端会打印服务端 schema 返回的查询结果 JSON服务端终端则会打印useLogger的execute-start/execute-end日志。关键要点小结本示例证明 Envelopenvelop/core不绑定任何特定 HTTP 框架或传输层示例目录examples/envelop/下并列的 apollo-server、graphql-ws、graphql-sse、graphql-socket.io 等示例展示了同一套envelop() 插件机制接入不同传输协议的方式envelop()返回的getEnveloped是“按操作实例化”的执行函数工厂见 create.ts在 Socket.IO 场景中通过getParameter回调把 socket 级信息注入初始 contextuseSchema通过onPluginInit注入 schemauseLogger通过onExecute/onSubscribe提供执行可观测性两者都是插件钩子体系的直接体现运行前提仓库根目录pnpm install、Node 18、按 README 顺序执行pnpm run start与pnpm run test:client示例包为private: true仅用于学习参考不作为 npm 包发布。赞分享后端API设计【免费下载链接】graphql-yoga Rewrite of a fully-featured GraphQL Server with focus on easy setup, performance great developer experience. The core of Yoga implements WHATWG Fetch API and can run/deploy on any JS environment.项目地址https://gitcode.com/gh_mirrors/gr/graphql-yoga点击查看免费下载相关推荐Next.js Pages Router 集成 Socket.IO 实战基于自定义 Server 的实时通信示例Next.js Pages Router 集成 Socket.IO 实战基于自定义 Server 的实时通信示例 本文基于 socket.io 仓库中的 ne后端即时通讯WebSocket基于 Prisma 与 graphql-yoga 实现 GraphQL 权限控制从数据模型到 Resolver 实战基于 Prisma 与 graphql yoga 实现 GraphQL 权限控制从数据模型到 Resolver 实战 本文是一篇面向 GraphQL 服务端开后端数据库GraphQL基于 Next.js 与 Nhost 实现认证与实时 GraphQL 的完整示例with-nhost-auth-realtime-graphql实战指南基于 Next.js 与 Nhost 实现认证与实时 GraphQL 的完整示例with nhost auth realtime graphql实战指南 导前端后端Web框架SSR前端构建上一篇7个实用技巧掌握rr调试框架中的录制与回放核心功能下一篇DeiT3_small_patch16_224.fb_in1k vs 传统CNN为什么Transformer是图像分类的未来创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考