首页
/ GraphQL Yoga 从 V1 迁移到 V2 完全指南

GraphQL Yoga 从 V1 迁移到 V2 完全指南

2025-07-07 02:07:32作者:沈韬淼Beryl

前言

GraphQL Yoga 是一个功能强大且易于使用的 GraphQL 服务器实现。随着 V2 版本的发布,它带来了许多架构上的改进和新特性。本文将详细介绍如何从 V1 版本平滑迁移到 V2 版本,涵盖服务器配置、上下文处理、中间件、订阅等多个核心功能的变化。

安装更新

首先需要更新 graphql-yoga 包:

npm install graphql-yoga
# 或
yarn add graphql-yoga

服务器配置变化

基本服务器创建

V1 版本使用类构造服务器,而 V2 改为使用 createYoga 函数。同时,typeDefsresolvers 现在需要通过 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 使用 pipefilter 替代 V1 的 withFilter

import { pipe, filter } from 'graphql-yoga'

pipe(
  context.subscribe('randomNumber'),
  filter(value => value > args.greaterThan)
)

总结

从 GraphQL Yoga V1 迁移到 V2 主要涉及以下变化:

  1. 服务器创建方式从类改为函数式
  2. 指令处理使用 mapSchema API
  3. 上下文请求对象遵循 Fetch API 标准
  4. 中间件需要额外安装插件
  5. 订阅协议改为 SSE
  6. PubSub 实现更类型安全

这些变化带来了更好的性能、类型安全和现代 Web 标准支持。按照本文指南,您可以顺利完成迁移并享受 V2 版本的新特性。