GraphQL 是一种用于 API 的查询语言,也是一个用于执行查询的运行时环境。与传统的 REST API 不同,GraphQL 允许客户端精确地请求所需要的数据,而不多也不少,从而优化了数据的获取过程。它通过一个单一的端点接收所有的请求,客户端可以组合多个资源查询成一个请求,而不需要多个 HTTP 请求。GraphQL 的灵活性和高效性使得它非常适合于动态数据结构和复杂的应用程序,尤其在需要高效数据传输和跨平台交互的情况下非常受欢迎。
1. Graphql 定义和解析
- 定义 schema
schema定义字段的类型、数据的结构。当我们进行一些错误的操作的时 GraphQL 引擎会告诉我们哪里有问题,和详细的错误信息,对开发调试十分友好。
GraphQL 中内置有一些类型 String、Int、Float、Boolean、ID,用户也可以定义自己的类型
type User {
id: ID
email: String
image: String
role: Role
posts: [Post]
}
enum Role {
ADMIN
USER
}
type Post {
id: ID
category: String
description: String
title: String
likes: [User]
}
从表中可以看出,一名作者可以用多篇文章,一篇文章也可以有多个用户点赞
- 定义可以数据的查询
查询所有文章,!表示非空,语法和TS几乎一样
// graphql/schema.ts
export const typeDefs = `
type Query {
posts: [Post]!
}
`
也可以根据文章id,查询某个具体的文章
// graphql/schema.ts
export const typeDefs = `
type Query {
post(id: ID!): Post!
}
`
- 定义数据的变更
定义文章的增删改
// graphql/schema.ts
export const typeDefs = `
...
type Mutation {
createPost(category: String!, description: String!, title: String!): Post!
deletePost(id: ID!): Post!
updatePost(category: String, description: String, id: String, title: String): Post!
}
`
- 定义解析函数
当前端请求信息传递到后端时,需要由对应的解析函数来提供响应数据,比如查询所有文章,这里就可以使用前面的prisma查询数据库
// /graphql/resolvers.ts
import prisma from '../lib/prisma'
export const resolvers = {
Query: {
posts: () => {
return prisma.post.findMany()
},
},
}
3.创建Graphql服务
- 安装依赖
pnpm add graphql graphql-yoga
graphql-yoga是一款流行的graphql服务器框架,内置了 GraphQL Playground,方便开发者测试和调试 API,适合快速开发和学习
- 创建服务接口
// src/api/graphql/route.ts
import { createSchema, createYoga } from 'graphql-yoga'
import { resolvers } from '../../graphql/resolvers'
import { typeDefs } from '../../graphql/schema'
import { NextRequest } from 'next/server'
const { handleRequest } = createYoga({
schema: createSchema({
typeDefs,
resolvers,
}),
})
export async function GET(request: NextRequest) {
return handleRequest(request, {} as any)
}
export async function POST(request: NextRequest) {
return handleRequest(request, {} as any)
}
现在执行pnpm dev,访问http://localhost:3000/api/graphql/,即可看到 GraphiQL Playground,输入以下代码,查询文章列表数据,指定返回Post模型中的 id和title字段
query {
posts {
id
title
}
}