CodeRoad Map 程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。
由 程序员柏风 独立维护 · 关于作者
学习 更多
服务端库 — CodeRoadMap
服务端库
这一课你将能做到
用 graphql-js / Apollo Server / Yoga 任选一个跑通最小可运行服务
说出 Java 生态(Spring for GraphQL)与 Node 生态的对应能力栈
为项目选型时讲清「底层引擎 / 全家桶 / 现代轻量」三个维度的权衡
为什么要学
GraphQL 是规范不是实现。学完语言与执行模型,你必须知道主流服务端库的能力差异:谁自带 IDE、谁支持文件上传、谁跟进了 graphql-ws 新协议、谁和 Spring 生态原生集成。选错库的代价不是跑不起来,而是两年后被版本锁定拖住、迁移成本高昂。
人话:库就是施工队——有的只砌墙(引擎),有的自带家具(全家桶),有的连物业都包了(框架集成)——看你要盖什么房。
先建立图像
选型决策树:
想手写每一步、理解引擎原理? → graphql-js(Node)/ graphql-java(JVM)
想要开箱即用、生态最丰富? → Apollo Server(Node)
想要现代协议 + 最小依赖? → GraphQL Yoga / Pothos(Node)
团队在 Spring Boot 技术栈里? → Spring for GraphQL(官方出品)
Node 生态主要库一览:
库 定位 特点 graphql-js 核心引擎 解析 + 校验 + 执行,不含 HTTP 层 apollo-server 全功能服务器 IDE/插件/指标齐全,生态最大,体积最大 graphql-yoga 轻量现代服务器 graphql-ws/SSE/上传/新 HTTP 规范全内置 pothos Code-first 构建器 从 TS 类型生成 Schema type-graphql Code-first 装饰器 类 + 装饰器写 Schema
跟着做
步骤 1:graphql-js 手写最小引擎(理解原理)
npm install graphql
const { buildSchema, graphqlSync } = require('graphql')
const schema = buildSchema(`type Query { ping: String }`)
const root = { ping: () => 'pong' }
const result = graphqlSync({ schema, source: '{ ping }', rootValue: root })
console.log(result) // { data: { ping: 'pong' } }
graphql-js 提供 AST 解析、Schema 构建、执行引擎,但不提供 HTTP 路由、WebSocket、IDE。它适合自定义网关/胶水层,不适合直接扛生产流量。
步骤 2:Apollo Server 最小服务
npm install @apollo/server graphql
import { ApolloServer } from '@apollo/server'
import { startStandaloneServer } from '@apollo/server/standalone'
const typeDefs = `#graphql
type Query { lesson(slug: String!): Lesson }
type Lesson { id: ID! title: String! }
`
const resolvers = {
Query: { lesson: (_p, { slug }) => ({ id: slug, title: '样例课时' }) }
}
const server = new ApolloServer({ typeDefs, resolvers })
const { url } = await startStandaloneServer(server, { listen: { port: 4000 } })
console.log(url) // 自带 Apollo Sandbox IDE
Apollo Server 自带请求解析、校验执行、IDE、错误格式化、插件系统。注意:从 v4 起不再捆绑 Express,HTTP 框架适配要自己选(standalone / expressMiddleware)。
步骤 3:GraphQL Yoga(协议最现代) npm install graphql-yoga graphql
import { createYoga, createSchema } from 'graphql-yoga'
import { createServer } from 'node:http'
const yoga = createYoga({
schema: createSchema({
typeDefs: `type Query { ping: String }`,
resolvers: { Query: { ping: () => 'pong' } }
})
// 开箱自带:graphql-ws 订阅、SSE 订阅、multipart 文件上传、
// GraphQL over HTTP 新规范、GraphiQL
})
createServer(yoga).listen(4000, () => console.log('http://localhost:4000/graphql'))
Yoga 不绑定任何 HTTP 框架(可嵌入 Express/Fastify/Next.js),规范跟进最快。新项目、在意协议先进性的团队优先考虑。
步骤 4:Java 生态——Spring for GraphQL // build.gradle
implementation 'org.springframework.boot:spring-boot-starter-graphql'
implementation 'org.springframework.boot:spring-boot-starter-web'
@Controller
public class LessonController {
private final LessonService lessonService;
LessonController(LessonService lessonService) { this.lessonService = lessonService; }
@QueryMapping
public Lesson lesson(@Argument String slug) {
return lessonService.findBySlug(slug);
}
@SchemaMapping(typeName = "Lesson", field = "author")
public User author(Lesson lesson) {
return userService.findById(lesson.getAuthorId());
}
@BatchMapping(typeName = "Lesson", field = "author") // 内置批处理,治 N+1
public Map<Lesson, User> authorBatch(List<Lesson> lessons) {
return userService.findByLessons(lessons);
}
}
# application.properties
spring.graphql.graphiql.enabled=true
spring.graphql.schema.locations=classpath:graphql/
Spring for GraphQL 封装 graphql-java(相当于 Node 里 Apollo 封装 graphql-js),与 Spring Security / 事务 / WebFlux 原生集成,@BatchMapping 是 DataLoader 的一等封装。Java 团队的正统选择。替代品:DGS Framework(Netflix,微服务联邦友好)。
步骤 5:联邦(Federation)初体验 # 课时服务子图
type Lesson @key(fields: "id") { id: ID! title: String! }
# 用户服务子图
type User @key(fields: "id") { id: ID! name: String! }
# 用户服务里扩展 Lesson
extend type Lesson @key(fields: "id") {
id: ID! @external
author: User # 网关在两个子图间自动 join
}
网关用 Apollo Router / Hive Gateway。联邦是「微服务时代的 GraphQL 组织方式」,单服务阶段不必引入。
讲清楚要点
graphql-js 是引擎不是服务器 :学原理用它,扛生产 HTTP 请用上层框架。
Apollo Server = 全家桶 :IDE、插件、指标、追踪生态最全;代价是体积与大版本锁定,v3→v4 是破坏性升级。
Yoga = 协议先锋 :graphql-ws / SSE / 新 HTTP 规范 / 文件上传全内置,零框架绑定;生态插件比 Apollo 少但核心场景齐全。
Java 正统是 Spring for GraphQL :注解式编程、@BatchMapping 治 N+1、Spring 全家桶集成;graphql-java-kickstart 已是上一代方案。
Code-first vs Schema-first :SDL 先行利于前后端契约并行开发;注解/类型生成先行利于重构与 IDE 提示。无论哪种,把产出的 schema.graphql 提交版本库 ,作为前端 codegen 的契约快照。
文件上传、订阅、批处理不在核心规范 :选型时逐条核对库的扩展支持矩阵,别默认都有。
库只解决解析执行 :深度/复杂度护栏、持久化查询、监控追踪是横切工程,靠插件或自建中间件补齐。
你可能会懵的地方
graphql-js 和 Apollo Server 什么关系?
Apollo Server 依赖 graphql-js 做底层解析与执行,自己包装 HTTP/WebSocket/IDE/插件层。同理 Spring for GraphQL 封装 graphql-java。
Apollo Server 4 相比 3 改了什么?
移除捆绑的 Express、重设计插件 API、错误信息生产默认脱敏。新项目直接用 4。
Yoga 能和 Express/Koa 一起用吗?
能。Yoga 本身是 fetch API 风格的 handler,可挂到任何 Node 框架或 Serverless 运行时。
Code-first 还要维护 SDL 文件吗?
不手写,但要生成并提交快照:一是前端 codegen 需要 schema 输入,二是 PR 评审能直接看到契约 diff。
Node 和 Java 的 GraphQL 服务能共存吗?
能,且常见:Node 做 BFF/联邦网关贴近前端,Java 做核心领域子图——契约只有 GraphQL 协议本身。
错法对照 错法 问题 正解 手写 HTTP 层 + graphql-js 上生产 重复造轮、协议细节踩坑 用 Apollo Server / Yoga / Spring 不锁库版本,大版本随缘升 升级即重写 锁定 minor,规划升级窗口 全公司共享一个大 Schema 跨团队互相踩脚 Federation 拆子图 + 网关合并 Java 团队为 GraphQL 强上 Node 服务 生态割裂、运维两套 Spring for GraphQL 原生落地 不导出 SDL 快照 前端类型生成无输入 构建期输出 schema.graphql 并入库 默认所有库都支持上传/订阅 上线才发现缺能力 选型时核对扩展协议支持矩阵
卡点急救
IDE 打不开 / 404 :各库 IDE 路径不同(Apollo Sandbox 在 /,Spring GraphiQL 在 /graphiql,Yoga 在 /graphql),先确认库与路径配置。
多文件 Schema 合并报重复类型 :多处定义了 type Query,保留一处基础定义、其余文件用 extend type Query。
升级 Apollo Server 后 import 报错 :v4 全面转向 ESM,把 require 换成 import,并确认 package.json 中 type 字段为 module。
面试常问
graphql-js 和 Apollo Server 的区别与关系?
graphql-js 是参考实现引擎(解析/校验/执行),不含 HTTP 层;Apollo Server 在其上封装了 HTTP 适配、IDE、插件体系与生产特性。Java 侧对应关系是 graphql-java 与 Spring for GraphQL。
服务端库选型的考量维度?
协议跟进度(graphql-ws、over-HTTP 新规范、上传)、生态与插件、团队语言栈、版本升级策略、联邦支持。Node 新项目可选 Yoga,存量大生态选 Apollo,Java 选 Spring for GraphQL。
什么是 Apollo Federation?
多团队各自维护子图 Schema,通过 @key 等指令声明实体关联,网关(Apollo Router 等)把跨子图的查询自动拆分 join。解决单一大 Schema 的多团队协作与独立部署问题。
自测三问
graphql-js 为什么不建议直接用于生产 HTTP 服务?
Spring for GraphQL 里治 N+1 的注解是哪个?
Schema-first 项目里为什么仍建议把生成的 schema.graphql 提交版本库?
小结一句话 服务端库的选择本质是「引擎 / 全家桶 / 框架集成」的定位题:graphql-js 教原理,Apollo Server 给生态,Yoga 追协议,Spring for GraphQL 是 Java 正统;库管解析执行,护栏与治理永远要自己补。
延伸