apollo-server 和 express-graphql 都是用于在 Node.js 环境中构建 GraphQL 服务器的库,但它们的定位和维护状态截然不同。apollo-server 是一个功能完整的框架,提供内置的缓存、插件系统和联合网关支持,适合复杂的企业级应用。express-graphql 是一个轻量级的 Express 中间件,旨在快速将 GraphQL 挂载到现有 Express 应用中,但目前已停止维护。
在 Node.js 生态中,apollo-server 和 express-graphql 都曾是构建 GraphQL API 的主流选择。它们都解决了将 GraphQL schema 暴露为 HTTP 端点的问题,但在架构设计、扩展能力和维护状态上存在巨大差异。对于正在做技术选型的开发者来说,理解这些差异至关重要 — 尤其是考虑到它们当前的维护状态。
这是选择这两个包之前必须了解的最重要信息。两者在 npm 上均带有弃用或维护模式警告。
apollo-server 指的是 Apollo Server v3。官方已将其置于维护模式,推荐使用 v4 版本(包名为 @apollo/server)。
// apollo-server (v3 - 维护模式)
const { ApolloServer } = require('apollo-server');
// 新项目应使用:const { ApolloServer } = require('@apollo/server');
express-graphql 已由 GraphQL 基金会正式弃用,仓库已归档,不再接受新功能或安全修复。
// express-graphql (已弃用)
const graphqlHTTP = require('express-graphql');
// 官方建议迁移至:@apollo/server 或 graphql-http
💡 建议:如果是新项目,请直接使用
@apollo/server。如果是旧项目,请制定迁移计划,避免技术债务累积。
两者的集成模式反映了不同的设计哲学。apollo-server 倾向于作为独立服务器运行,而 express-graphql 设计为 Express 应用的一部分。
apollo-server 默认启动自己的 HTTP 服务器,虽然也可以集成到 Express 中,但推荐 standalone 模式。
// apollo-server: 独立启动
const { ApolloServer } = require('apollo-server');
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
express-graphql 必须依附于 Express 应用,作为中间件挂载到特定路由。
// express-graphql: 中间件模式
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: makeExecutableSchema({ typeDefs, resolvers }),
graphiql: true
}));
app.listen(4000);
在 GraphQL 解析过程中,context 用于传递认证信息、数据库连接等共享数据。两者的处理方式不同。
apollo-server 提供专门的 context 配置项,支持异步初始化,适合处理复杂的认证逻辑。
// apollo-server: 专用 Context 配置
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }) => {
const token = req.headers.authorization;
const user = await validateToken(token);
return { user };
}
});
express-graphql 直接接收一个 context 对象或函数,但功能较为基础,通常直接复用 Express 的 req 对象。
// express-graphql: 简单 Context 传递
app.use('/graphql', graphqlHTTP({
schema,
context: { req }, // 直接传递 request 对象
graphiql: true
}));
GraphQL 的错误处理直接影响前端调试体验。apollo-server 提供了更强大的错误格式化能力。
apollo-server 内置 formatError 钩子,可以隐藏内部堆栈信息,统一错误结构。
// apollo-server: 自定义错误格式
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: (error) => {
return {
message: error.message,
code: error.extensions?.code || 'INTERNAL_ERROR'
};
}
});
express-graphql 也支持 customFormatErrorFn,但配置选项较少,且不再更新以适应新标准。
// express-graphql: 基础错误格式化
app.use('/graphql', graphqlHTTP({
schema,
customFormatErrorFn: (error) => ({
message: error.message,
locations: error.locations
})
}));
当需要添加日志、缓存或追踪功能时,扩展性变得关键。
apollo-server 拥有成熟的插件系统(Plugins),可以监听请求生命周期各个阶段。
// apollo-server: 插件系统
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [
{
requestDidStart: () => ({
willSendResponse: () => console.log('Response sent')
})
}
]
});
express-graphql 依赖 Express 的中间件链,需要在路由前后手动添加逻辑,缺乏 GraphQL 特定的生命周期钩子。
// express-graphql: 依赖 Express 中间件
app.use('/graphql', (req, res, next) => {
console.log('Request received');
next();
}, graphqlHTTP({ schema }));
尽管存在差异,这两个库在核心功能上有很多重叠,因为它们都基于 graphql-js。
// 两者通用的 Schema 定义
const typeDefs = `#graphql
type Query {
hello: String
}
`;
const resolvers = { Query: { hello: () => 'World' } };
// apollo-server: 默认启用 (开发环境)
// express-graphql: 需显式配置
graphqlHTTP({ schema, graphiql: true })
// 两者通用的请求结构
// POST /graphql
// Body: { "query": "{ hello }" }
| 特性 | apollo-server | express-graphql |
|---|---|---|
| 维护状态 | ⚠️ 维护模式 (推荐迁至 v4) | ❌ 已弃用 (不再更新) |
| 集成模式 | 🚀 独立服务器为主 | 🧩 Express 中间件 |
| 上下文管理 | 🛠️ 异步 Context 函数 | 📦 简单对象传递 |
| 错误处理 | 🛡️ 强大格式化钩子 | 📝 基础格式化支持 |
| 扩展能力 | 🔌 专用插件系统 | 🔗 依赖 Express 中间件 |
| 适用场景 | 企业级、复杂架构 | 旧项目维护、简单脚本 |
apollo-server 就像是一个功能齐全的工程车 🚛 — 虽然 v3 版本已进入维护期,但其架构设计依然 robust,适合需要稳定性能监控和复杂扩展的场景。迁移到 @apollo/server 后,它能继续支撑大型应用。
express-graphql 就像是一个简易工具包 🧰 — 曾经非常流行,但现在已生锈。它的简单性在早期是优势,但现在成了安全隐患。除非你被锁定在无法修改的旧系统中,否则不应再使用它。
核心结论:对于现代 Node.js GraphQL 开发,请跳过这两个包的直接选择,转而采用 @apollo/server。它继承了 apollo-server 的优点,修复了架构问题,并保持了活跃维护。技术选型不仅要看功能,更要看未来 — 选择一个活跃的生态比选择一个简单的库更重要。
仅建议在维护现有的 Apollo Server v3 项目时使用,新项目应直接采用 @apollo/server。如果你需要内置的性能监控、复杂的插件系统或 Apollo 联邦架构,这是更合适的选择。虽然包名已标记为维护模式,但其生态迁移路径清晰,适合长期演进。
不建议在任何新项目中选择此包,因为它已正式弃用且不再接收安全更新。仅在无法重构的遗留系统中暂时保留,且应尽快计划迁移至 @apollo/server 或 graphql-http。它的简单性不再足以抵消安全风险和功能缺失。

Apollo Server is a community-maintained open-source GraphQL server. It works with many Node.js HTTP server frameworks, or can run on its own with a built-in Express server. Apollo Server works with any GraphQL schema built with GraphQL.js--or define a schema's type definitions using schema definition language (SDL).
Read the documentation for information on getting started and many other use cases and follow the CHANGELOG for updates.
Apollo Server is built with the following principles in mind:
Anyone is welcome to contribute to Apollo Server, just read CONTRIBUTING.md, take a look at the roadmap and make your first PR!
To get started with Apollo Server:
npm install apollo-server-<integration> graphqlThere are two ways to install Apollo Server:
apollo-server package.express, koa, hapi, etc.), use the appropriate Apollo Server integration package.For more info, please refer to the Apollo Server docs.
In a new project, install the apollo-server and graphql dependencies using:
npm install apollo-server graphql
Then, create an index.js which defines the schema and its functionality (i.e. resolvers):
const { ApolloServer, gql } = require('apollo-server');
// The GraphQL schema
const typeDefs = gql`
type Query {
"A simple type for getting started!"
hello: String
}
`;
// A map of functions which return data for the schema.
const resolvers = {
Query: {
hello: () => 'world',
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Due to its human-readability, we recommend using schema-definition language (SDL) to define a GraphQL schema--a
GraphQLSchemaobject fromgraphql-jscan also be specified instead oftypeDefsandresolversusing theschemaproperty:const server = new ApolloServer({ schema: ... });
Finally, start the server using node index.js and go to the URL returned on the console.
For more details, check out the Apollo Server Getting Started guide and the fullstack tutorial.
For questions, the Apollo community forum is a great place to get help.
While the standalone installation above can be used without making a decision about which web framework to use, the Apollo Server integration packages are paired with specific web frameworks (e.g. Express, Koa, hapi).
The following web frameworks have Apollo Server integrations, and each of these linked integrations has its own installation instructions and examples on its package README.md:
A request context is available for each request. When context is defined as a function, it will be called on each request and will receive an object containing a req property, which represents the request itself.
By returning an object from the context function, it will be available as the third positional parameter of the resolvers:
new ApolloServer({
typeDefs,
resolvers: {
Query: {
books: (parent, args, context, info) => {
console.log(context.myProperty); // Will be `true`!
return books;
},
}
},
context: async ({ req }) => {
return {
myProperty: true
};
},
})
The Apollo Server documentation contains additional details on how to get started with GraphQL and Apollo Server.
The raw Markdown source of the documentation is available within the docs/ directory of this monorepo--to contribute, please use the Edit on GitHub buttons at the bottom of each page.
If you wish to develop or contribute to Apollo Server, we suggest the following:
Fork this repository
Install Direnv (a tool that automatically sets up environment variables in project directories) or nvm. We use nvm to ensure we're running the expected version of Node (and we use Direnv to install and run nvm automatically).
Install the Apollo Server project on your computer
git clone https://github.com/[your-user]/apollo-server
cd apollo-server
direnv allow # sets up nvm for you; if you installed nvm yourself, try `nvm install` instead
npm install
npm test
npm run pretest && npx jest packages/apollo-server-foo/src/__tests__/bar.test.ts. Note that you do need to re-compile TypeScript before each time you run a test, or changes across packages may not be picked up. Instead of running npm run pretest from scratch before each test run, you can also run tsc --build tsconfig.json --watch in another shell, or use the VSCode Run Build Task to run that for you.Are you stuck? Want to contribute? Come visit us in the Apollo community forum!
Apollo builds open-source software and a graph platform to unify GraphQL across your apps and services. We help you ship faster with:
Check out the Odyssey learning platform, the perfect place to start your GraphQL journey with videos and interactive code challenges. Join the Apollo Community to interact with and get technical help from the GraphQL community.