普通视图

发现新文章,点击刷新页面。
昨天以前首页

🧠 Next.js × GraphQL Yoga × GraphiQL:交互式智能之门

作者 LeonGao
2025年11月7日 09:13

image.png

“当 Next.js 提供空间容器,GraphQL Yoga 就成为了灵魂管家。”


一、GraphQL 的哲学底色:

REST: “我有一堆API,你得一个个调用。”
GraphQL: “别闹,一次请求要啥我都打包返回。”

GraphQL 的三个灵魂元素:

类型 说明 对应概念
Query 读取(想了解点啥) GET 的精神继承者
🛠️ Mutation 写入(要改点啥) POST/PUT 的理性重组
💧 Scalar 原子级数据单元 String, Int, Float, Boolean, ID

二、📦 初始化工程:Next.js + Yoga

首先你需要在项目中安装 Yoga 与 GraphQL 基础:

npm install graphql @graphql-yoga/node

Next.js(>=13)提供了 App Router,我们可以在 /app/api/graphql/route.ts/app/api/graphql/route.js 中挂载 Yoga 服务。


三、🧩 实现一个极简的 Yoga 入口

// /app/api/graphql/route.js
import { createSchema, createYoga } from 'graphql-yoga';

const typeDefs = /* GraphQL */ `
  type Query {
    hello(name: String): String
  }

  type Mutation {
    shout(message: String!): String
  }

  scalar DateTime
`;

const resolvers = {
  Query: {
    hello: (_, { name }) => `你好, ${name || '世界'} 👋`,
  },
  Mutation: {
    shout: (_, { message }) => message.toUpperCase() + '!!! 🔊',
  },
  DateTime: new Date(), // 示例 Scalar
};

const { handleRequest } = createYoga({
  schema: createSchema({ typeDefs, resolvers }),
  graphqlEndpoint: '/api/graphql',
  fetchAPI: { Request, Response },
});

export { handleRequest as GET, handleRequest as POST };

🎯 亮点解析:

  1. createYoga() 自动提供 GraphiQL(浏览器内交互界面);

  2. 你可以直接在浏览器访问:

    http://localhost:3000/api/graphql
    

    👀 然后你就会看到 GraphiQL;

  3. Yoga 内建性能优化 + Next.js Edge Runtime 兼容。


四、🚀 GraphiQL 交互:Query / Mutation 实操

打开 GraphiQL 页面后,可以尝试以下几个示例。

📤 Query 示例:

query {
  hello(name: "Neo")
}

💬 返回输出:

{
  "data": {
    "hello": "你好, Neo 👋"
  }
}

🪄 Mutation 示例:

mutation {
  shout(message: "GraphQL Yoga is awesome")
}

💬 返回:

{
  "data": {
    "shout": "GRAPHQL YOGA IS AWESOME!!! 🔊"
  }
}

🧮 Scalar 示例:

我们可以自定义一个 DateTime 标量类型(Scalar Type),用于时间序列传输。
在 Yoga 中可以使用 graphql-scalars

npm install graphql-scalars
import { DateTimeResolver, DateTimeTypeDefinition } from 'graphql-scalars';

const typeDefs = /* GraphQL */ `
  ${DateTimeTypeDefinition}

  type Query {
    now: DateTime!
  }
`;

const resolvers = {
  DateTime: DateTimeResolver,
  Query: {
    now: () => new Date(),
  },
};

🕰️ Query:

query {
  now
}

🎯 返回:"2025-11-07T08:41:32Z"


五、🧰 官方 Yoga 文档入口

The Guild 团队维护的 Yoga 是 GraphQL 服务器中的黑马,
官方文档:
🔗 the-guild.dev/graphql/yog…

文档有这些黄金章节:

模块 功能
createYoga() 核心服务器接口
createSchema() 组装 TypeDefs + Resolvers
GraphiQL 内置交互编辑器
Plugins 扩展中间件(如 CORS、安全性、缓存)
Subscriptions 支持 WebSocket 实时推送

六、🧠 底层机制揭秘

GraphQL Yoga = “HTTP + GraphQL + Streaming + Subscriptions” 的完美合成。

具体流程如下:

  1. HTTP 层:Next.js Edge Runtime 接收 GET/POST 请求;
  2. Parsing 层:Yoga 解析 payload(query 字符串或 mutation 数据);
  3. Schema 层:类型系统匹配 + resolver 绑定;
  4. Response 层:构造 JSON Response;
  5. GraphiQL 模式:实时调试结果、查询历史保存、本地缓存变量。

🧩 伪代码底层逻辑:

handleRequest(req) {
  const query = extractGraphQL(req);
  const schema = buildSchema();
  const result = executeGraphQL({ schema, query });
  return Response.json(result);
}

七、💡 拓展方向

功能 实现思路
🔍 Subscription 实时更新 集成 WebSocket 支持 Yoga Subscriptions
🧱 Remote Schema Stitching 聚合多个微服务的 GraphQL Schema
🔐 Auth Guard 结合 NextAuth.js 注入 session 验证
⚡ Edge Runtime 优化 Yoga 支持 Edge Function 启动
🧠 Embodied AI Integration 用具身智能代理自动生成 GraphQL Query 😄

八、🎨 一个小的互动架构图(可视说明)

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Next.js × Yoga GraphQL 流程图</title>
<style>
body {
  font-family: 'Segoe UI', sans-serif;
  background: #fafafa;
  padding: 20px;
  text-align: center;
}
.node {
  display: inline-block;
  background: #dfe6e9;
  border-radius: 8px;
  padding: 10px 20px;
  margin: 10px;
  font-weight: bold;
}
.arrow {
  font-size: 24px;
  color: #636e72;
}
</style>
</head>
<body>
<h3>Next.js + GraphQL Yoga 数据流示意图</h3>
<div>
  <div class="node">Client (GraphiQL)</div>
  <div class="arrow">➡️</div>
  <div class="node">Next.js Edge API</div>
  <div class="arrow">➡️</div>
  <div class="node">Yoga Schema</div>
  <div class="arrow">➡️</div>
  <div class="node">Resolvers</div>
  <div class="arrow">➡️</div>
  <div class="node">Result JSON</div>
</div>
</body>
</html>

九、结语:

下一次当你在浏览器中打开 http://localhost:3000/api/graphql
请记得:
你看到的不是一个普通接口,
而是Web 智能交互的下一层语言接口

GraphiQL 是你的显微镜,Yoga 是你的实验室,
而 Next.js —— 是那台永不休眠的服务器灵魂。

🌐 《GraphQL in Next.js 初体验》中文笔记

作者 LeonGao
2025年11月6日 09:21

🧩 一、概览:Next.js + GraphQL 是怎么“对话”的?

Next.js 是前后端一体框架,而 GraphQL 是一种 API 查询语言。结合起来后:
🤝 Next.js 提供运行环境
🧠 GraphQL 提供数据语义接口

简单理解:

  • Next.js = 舞台和播放器(API 路径、页面渲染、Serverless 运行)
  • GraphQL = 剧本(Schema定义)、演员台词逻辑(Resolver)、导演策略(Context)

结构大致如下:

Next.js API Route ─┬─► ApolloServer / Yoga Server
                    │
                    └─► GraphQL Schema (定义数据结构)
                        └─► Resolver (具体处理逻辑)
                            └─► Context (跨请求共享上下文)

🧱 二、Schema:GraphQL 的“数据契约”

Schema 是 定义数据形状的语言模型
可以把它理解为数据库表结构 + API 文档的结合体。

示例 ⚙️

# ./graphql/schema.graphql
type User {
  id: ID!
  name: String!
  age: Int
}

type Query {
  users: [User!]!
  user(id: ID!): User
}

type Mutation {
  addUser(name: String!, age: Int): User
}

📘 要点笔记:

  • type:定义类型(用户、文章、评论等)
  • Query:读取数据的入口
  • Mutation:修改、创建、删除数据的入口

Schema 就像一份菜单,它定义了服务员能做的所有菜,但不做菜。
做菜的是 Resolver 👉


🧠 三、Resolver:GraphQL 的“大脑中枢”

Resolver 是 Schema 的执行器,它负责将查询请求映射到实际数据源
在 Next.js 中,一般写成 JS/TS 文件与 Schema 匹配。

示例 👇

// ./graphql/resolvers.js
const users = [
  { id: "1", name: "Neo", age: 29 },
  { id: "2", name: "Trinity", age: 27 },
];

export const resolvers = {
  Query: {
    users: () => users,
    user: (_, { id }) => users.find(u => u.id === id),
  },
  Mutation: {
    addUser: (_, { name, age }) => {
      const newUser = { id: String(users.length + 1), name, age };
      users.push(newUser);
      return newUser;
    },
  },
};

📘 要点笔记:

  • 每个字段对应一个函数。
  • 第一个参数 _ 通常是父级字段(这里未使用,可省略)。
  • 第二个参数 { id } 是客户端传入的变量。
  • Resolver 内不管 Schema 长啥样,它只需返回对应数据。

🌍 四、Context:连接“每个请求”的神经系统

Context 是 GraphQL 在请求周期中共享的环境对象
它的作用类似于:

  • 注入依赖(数据库实例、token 验证、用户状态)
  • 跨 Resolver 共享状态

示例:

import jwt from "jsonwebtoken";
import db from "./db.js";

export const createContext = ({ req }) => {
  const token = req.headers.authorization || "";
  let user = null;

  try {
    user = jwt.verify(token, process.env.JWT_SECRET);
  } catch (e) {
    console.log("token 无效或未提供");
  }

  return { db, user };
};

在 Resolver 中,就能这样访问:

Mutation: {
  addUser: (_, { name, age }, { db, user }) => {
    if (!user) throw new Error("未授权");
    return db.insertUser({ name, age });
  }
}

📘 要点笔记:

  • Context 在每次请求开始时创建(一次请求一次 Context)。
  • 经 Context 可安全访问外部资源且隔离状态。
  • 在 SSR 和 Serverless 模式的 Next.js 中非常实用。

⚙️ 五、在 Next.js 中整合 Apollo Server

在 Next.js 中最常见的方式是用 /api/graphql 作为后端入口。

// ./pages/api/graphql.js
import { ApolloServer } from "apollo-server-micro";
import { typeDefs } from "../../graphql/schema.js";
import { resolvers } from "../../graphql/resolvers.js";
import { createContext } from "../../graphql/context.js";

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

export const config = {
  api: { bodyParser: false },
};

export default server.createHandler({ path: "/api/graphql" });

💡 运行逻辑:

  1. 浏览器访问 /api/graphql
  2. Next.js 调用 ApolloServer 处理请求
  3. ApolloServer 根据 Schema 调用对应 Resolver
  4. Resolver 通过 Context 访问数据源
  5. 返回 JSON 响应

🖥️ 六、Next.js 前端调用示例

import { gql, useQuery } from "@apollo/client";

const ALL_USERS = gql`
  query {
    users {
      id
      name
      age
    }
  }
`;

export default function UsersList() {
  const { loading, error, data } = useQuery(ALL_USERS);
  if (loading) return <p>⏳ 加载中...</p>;
  if (error) return <p>❌ 出错啦: {error.message}</p>;
  return (
    <ul>
      {data.users.map(u => (
        <li key={u.id}>
          👤 {u.name}(年龄:{u.age ?? "未知"})
        </li>
      ))}
    </ul>
  );
}

在这里,前端只需声明「我想要什么」,
后端就帮你搞定「怎么算出来」。


💬 七、小结:三大组件一图流

<div style="max-width:720px;margin:auto;text-align:center;">
<svg width="100%" height="300" viewBox="0 0 720 300" xmlns="http://www.w3.org/2000/svg">
  <rect x="60" y="60" width="170" height="60" rx="10" fill="#A1C4FD" stroke="#333"/>
  <text x="145" y="95" text-anchor="middle" font-size="13">Schema (定义契约)</text>

  <rect x="280" y="60" width="170" height="60" rx="10" fill="#FDD692" stroke="#333"/>
  <text x="365" y="95" text-anchor="middle" font-size="13">Resolver (处理逻辑)</text>

  <rect x="500" y="60" width="170" height="60" rx="10" fill="#C2E9FB" stroke="#333"/>
  <text x="585" y="95" text-anchor="middle" font-size="13">Context (执行环境)</text>

  <line x1="230" y1="90" x2="280" y2="90" stroke="#000" stroke-width="2" marker-end="url(#arrow)"/>
  <line x1="450" y1="90" x2="500" y2="90" stroke="#000" stroke-width="2" marker-end="url(#arrow)"/>

  <defs>
    <marker id="arrow" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
      <path d="M0,0 L0,6 L9,3 z" fill="#333"/>
    </marker>
  </defs>
</svg>
<p style="font-size:13px;color:#666;">▲ Next.js GraphQL 三件套结构关系图</p>
</div>

🚀 八、为什么 Next.js 是 GraphQL 的理想宿主?

  1. Serverless Ready:API 路由天然适合部署 Apollo 或 Yoga Server。
  2. SSR + CSR 混合渲染:可直连 GraphQL 数据,从后端直出页面。
  3. Edge Runtime:未来的 Web AGI 场景(边缘智能体)可直接调用 GraphQL 层。
  4. TypeScript 一体化支持:Schema + Resolver 均能生成类型定义,开发丝滑。
❌
❌