首页 / 后端开发 / Apollo Server落地实战:

Apollo Server落地实战:把GraphQL查询、鉴权、分页和压测一次跑通

Roxi
Roxi 加速器 — 稳定·快速·安全
全球节点覆盖,支持所有主流平台,一键连接无需配置。新用户免费试用。
立即体验 →

开场:OK so,今天直接把GraphQL接口跑起来

品牌定位清晰视觉体系统一内容矩阵搭建社媒运营规划效果追踪复盘

各位 eccfy 的开发同学,屏幕看我!今天不是念概念,我们直接做一个Node GraphQL接口实战:用户列表、文章查询、JWT鉴权、分页、压测,全都现场敲。很多人搜“Apollo Server教程”“GraphQL分页怎么做”,最后卡在 Resolver 结构混乱、N+1 查询、错误码不好控。接下来我按真实项目拆。

先用免费官方方案:Node.js、Apollo Server、graphql、jsonwebtoken。限制也说清楚:小项目直接跑没问题;团队项目建议接 ORM、DataLoader、日志和网关,否则接口一多就难排查。

终端开干,创建项目:

mkdir gql-demo && cd gql-demo
npm init -y
npm i @apollo/server graphql jsonwebtoken
npm i -D nodemon

package.json 加启动命令:

{
  "scripts": {
    "dev": "nodemon index.js"
  },
  "type": "module"
}

Chapter 1:Schema先定边界,Resolver只做执行

🚀STEP 1环境搭建📋STEP 2编码实现⚙️STEP 3测试验证🔧STEP 4部署上线

Now watch this,我把屏幕切到 index.js。先写 Schema,别一上来就怼数据库。Schema 是前后端契约,字段少了前端骂你,字段乱了后端自己哭。

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import jwt from 'jsonwebtoken';

const users = [
  { id: '1', name: 'Aki', role: 'ADMIN' },
  { id: '2', name: 'Ming', role: 'USER' }
];

const posts = Array.from({ length: 30 }).map((_, i) => ({
  id: String(i + 1),
  title: `Post ${i + 1}`,
  authorId: i % 2 ? '1' : '2'
}));

const typeDefs = `#graphql
  type User { id: ID!, name: String!, role: String! }
  type Post { id: ID!, title: String!, author: User! }
  type PageInfo { page: Int!, pageSize: Int!, total: Int! }
  type PostPage { items: [Post!]!, pageInfo: PageInfo! }

  type Query {
    me: User
    posts(page: Int = 1, pageSize: Int = 10): PostPage!
  }
`;

接下来 Resolver。注意分页别直接把全部数据丢给前端;pageSize 我一般限制到 50,防止一次查询拖垮服务。这里也是“GraphQL分页怎么做”的核心答案:参数校验、总数返回、列表切片必须一起做。

const resolvers = {
  Query: {
    me: (_, __, ctx) => ctx.user || null,
    posts: (_, { page, pageSize }) => {
      const size = Math.min(pageSize, 50);
      const start = (page - 1) * size;
      return {
        items: posts.slice(start, start + size),
        pageInfo: { page, pageSize: size, total: posts.length }
      };
    }
  },
  Post: {
    author: (post) => users.find(u => u.id === post.authorId)
  }
};

Chapter 2:JWT鉴权怎么用?直接挂到context

中国45美国30日本12韩国8其他5

OK so,很多同学搜“GraphQL鉴权怎么用”,答案别搞复杂:认证放 context,授权放 Resolver 或业务层。我们先做认证。

const server = new ApolloServer({ typeDefs, resolvers });

const { url } = await startStandaloneServer(server, {
  listen: { port: 4000 },
  context: async ({ req }) => {
    const token = req.headers.authorization?.replace('Bearer ', '');
    if (!token) return {};
    try {
      return { user: jwt.verify(token, 'dev-secret') };
    } catch {
      return {};
    }
  }
});

console.log(`GraphQL ready at ${url}`);

生成一个测试 token:

node -e "console.log(require('jsonwebtoken').sign({id:'1',name:'Aki',role:'ADMIN'}, 'dev-secret'))"

如果你在搜“Apollo Server下载”,其实不用单独下载软件,npm 安装包就是官方路线。跟“油管怎么看”“免费VPN”“翻墙软件”这类网络问题不同,GraphQL 本身不需要特殊客户端,浏览器打开本地 4000 端口就能调。

Chapter 3:现场验证,前后对比看数据

启动:

npm run dev

浏览器打开 Apollo Sandbox,粘这个查询:

query {
  posts(page: 2, pageSize: 5) {
    items { id title author { name role } }
    pageInfo { page pageSize total }
  }
}

我本机 M2、Node 20 测试,冷启动约 620ms;连续请求 100 次,平均响应 31ms。注意,当前 demo 的 author 是内存 find,真实数据库会出现 N+1,下一步要用 DataLoader 批量查作者。

怎么确认它真的修好了:第一,posts 返回 5 条且 pageInfo.total 是 30;第二,带 Bearer token 请求 me 能返回 Aki,不带 token 返回 null;第三,把 pageSize 改成 999,实际返回不超过 50;第四,服务端无报错,终端没有未捕获异常。做到这四点,你的 GraphQL API 基础链路就通了。

如果只是学习,官方文档、npm、公司代理都够用;如果你所在网络访问开发资料不稳定,也可以把 Roxi 这类工具作为备选之一:https://wizzegroup.com。今天这期有用的话,评论区打“GraphQL”,我下一篇直接演示 DataLoader 和 Prisma 联动!