GraphQL Yoga 从 V1 迁移到 V2 完全指南
前言
GraphQL Yoga 是一个功能强大且易于使用的 GraphQL 服务器实现。随着 V2 版本的发布,它带来了许多架构上的改进和新特性。本文将详细介绍如何从 V1 版本平滑迁移到 V2 版本,涵盖服务器配置、上下文处理、中间件、订阅等多个核心功能的变化。
安装更新
首先需要更新 graphql-yoga
包:
npm install graphql-yoga
# 或
yarn add graphql-yoga
服务器配置变化
基本服务器创建
V1 版本使用类构造服务器,而 V2 改为使用 createYoga
函数。同时,typeDefs
和 resolvers
现在需要通过 createSchema
传递给 schema
属性。
V1 版本示例:
import { GraphQLServer } from 'graphql-yoga'
import { resolvers, typeDefs } from './schema'
const server = new GraphQLServer({ typeDefs, resolvers })
server.start()
V2 版本示例:
import { createServer } from 'http'
import { createSchema, createYoga } from 'graphql-yoga'
import { resolvers, typeDefs } from './schema'
const yoga = createYoga({
schema: createSchema({ typeDefs, resolvers })
})
const server = createServer(yoga)
server.listen(4000, () => {
console.info('Server is running on http://localhost:4000/graphql')
})
从文件加载类型定义
V1 可以直接提供文件路径作为 typeDefs
,而 V2 需要使用 Node.js 的 fs
模块。
V2 实现方式:
import * as fs from 'fs'
import * as path from 'path'
import { createSchema, createYoga } from 'graphql-yoga'
const yoga = createYoga({
schema: createSchema({
typeDefs: fs.readFileSync(path.join(__dirname, 'schema.graphql'), 'utf-8'),
resolvers
})
})
指令处理变化
V1 使用 directiveResolvers
,而 V2 推荐使用 mapSchema
API。
V2 指令实现示例:
import { mapSchema, getDirective, MapperKind } from '@graphql-tools/utils'
let schema = makeExecutableSchema({ typeDefs, resolvers })
schema = mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
const upperDirective = getDirective(schema, fieldConfig, 'uppercase')?.[0]
if (upperDirective) {
// 实现指令逻辑
}
return fieldConfig
}
})
上下文处理改进
V2 中的 context
函数与 V1 类似,但请求对象现在遵循 Fetch API 标准。
V2 上下文示例:
const yoga = createYoga({
schema,
context(initialContext) {
const authHeader = initialContext.request.headers.get('authorization')
return { db, authHeader }
}
})
中间件处理变化
V1 内置了 graphql-middleware
,而 V2 出于性能考虑不再默认包含。如果需要类似功能,可以使用 @envelop/graphql-middleware
插件。
V2 中间件实现:
import { useGraphQLMiddleware } from '@envelop/graphql-middleware'
const yoga = createYoga({
plugins: [useGraphQLMiddleware([permissions])]
})
替代 GraphQL Shield 的方案
V2 推荐使用以下方案替代 GraphQL Shield:
@envelop/generic-auth
:用于认证和简单的字段级授权@envelop/operation-field-permissions
:基于模式坐标的细粒度字段权限- GraphQL AuthZ:现代灵活的 GraphQL 授权层
订阅功能升级
V1 使用 subscriptions-transport-ws
协议,而 V2 改用 SSE (Server-Sent Events) 协议。
SSE 的优势
- 基于简单 HTTP 协议
- 内置重连和事件 ID 支持
- 更简单的协议
- 避免企业防火墙问题
类型安全的 PubSub
V2 引入了类型安全的 PubSub 实现:
import { createPubSub } from 'graphql-yoga'
const pubSub = createPubSub<{
randomNumber: [randomNumber: number]
}>()
事件过滤
V2 使用 pipe
和 filter
替代 V1 的 withFilter
:
import { pipe, filter } from 'graphql-yoga'
pipe(
context.subscribe('randomNumber'),
filter(value => value > args.greaterThan)
)
总结
从 GraphQL Yoga V1 迁移到 V2 主要涉及以下变化:
- 服务器创建方式从类改为函数式
- 指令处理使用
mapSchema
API - 上下文请求对象遵循 Fetch API 标准
- 中间件需要额外安装插件
- 订阅协议改为 SSE
- PubSub 实现更类型安全
这些变化带来了更好的性能、类型安全和现代 Web 标准支持。按照本文指南,您可以顺利完成迁移并享受 V2 版本的新特性。