楔子
一般傳統的 RESTFul API 通常有一個缺點, 就是要設定不同的路由(routes)來當作入口點, 久而久之就會有一堆的路由網址,也不敢去做任何的修正, 誰敢擔責任改了是不是會噴錯, 慢慢的就也放著讓它愈長愈大了,當然後來有些 library 像 swagger 可以幫助自動產生文件, 但也還是需要做些設定,這也慢慢的讓 graphQL 有開始長大的空間。
GraphQL
主要的精神架構為, Server 設定好條件(資料的格式 schema & 路由 routes),
這時透過查詢語法(Query Language)所帶來的參數,經由 business logic 的轉換(資料 CRUD)再回拋資料。
Server 元件
要架一個 GraphQL Server,思考一下要什麼東西??
就觀念上就要有三個東西 = Server + 資料格式 Schema + 一些數據的處理
- Server: 可以用 ExpressJS,Apollo Server.. graphQL server
- Scehma: 基本上就是一個定義檔,可以用不同語言的格式 type & schema,應該各語言都有一些轉換方式
- logic: 通常就會牽涉到「數據」的處理,就會扯到 DB ,就會有一些 ORM 使用(eg. sequelize, typeorm, prisma..等等)
server
var express = require('express')
var { graphqlHTTP } = require('express-graphql')
var { buildSchema } = require('graphql')
var schema = buildSchema(`
type Query {
hello: String
}
`)
var root = { hello: () => 'Hello world!' }
var app = express()
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}))
app.listen(4000, () => console.log('Now browse to localhost:4000/graphql'))
定義(Schema)
GraphQL 的 schema 定義其實很像 typescript(或許有小夥伴說這是什?以後再做介紹囉)
type Character {
name: String!
appearsIn: [Episode!]!
}
查詢語法(Query Language)
有 GUI 的查詢語法
{
hero {
name
appearsIn
}
}
配合查詢語法所用的 resolver(business logic)
類似說,當查詢語法進來時,會有一些變數(ctx, parent…),這時吃到這些參數時,
所進行的一連串資料的處理(eg. ORM 拉資料 > 做處理 > 吐回資料)
var postType = new GraphQLObjectType({
name: ‘Post’,
fields: {
body: {
type: GraphQLString,
resolve: (post, args, context, { rootValue }) => {
// return the post body only if the user is the post's author
if (context.user && (context.user.id === post.authorId)) {
return post.body
}
return null
}
}
}
})