前一篇講了 REST 的一些缺點,還有 GraphQL 如何解決這些問題,這篇將帶大家深入細節與實作一邊了解 GraphQL。
因為筆者的專長是 JavaScript,所以這篇的實作也將圍繞在 Node 上面,不過 GraphQL 是不依賴在任何程式語言上的查詢語言,所以用各種程式語言去實作都是可以的,如果要查詢各種程式語言既有的套件可以參考 Awesome GraphQL。
在開始之前,必須先安裝三個套件,graphql 是實作了 GraphQL 核心的 JavaScript 套件負責解析 AST、執行 Validation、建構基礎的 Type 與 Schema 等等,express-graphql 則是讓 Express 可以處理 GraphQL Schema 的套件,當然還有我們的 Server - express,跟前面一樣我們用 npm
或是 yarn
來安裝:
npm install --save graphql express-graphql express
yarn add graphql express-graphql express
然後建 GraphQLSchema.js
以及 server.js
這兩個檔案放一下以下內容:
// GraphQLSchema.js
const { buildSchema } = require('graphql');
exports.schema = buildSchema(`
type Query {
hello: String
}
`);
exports.rootValue = {
hello: () => 'Hello world!',
};
// server.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { schema, rootValue } = require('./GraphQLSchema');
const app = express();
app.use('/graphql', graphqlHTTP({
schema,
rootValue,
graphiql: true,
}));
app.listen(3000);
打開 http://localhost:3000/graphql
如果能看到這個畫面那就成功囉!
這是個叫做 GraphiQL 的強大工具,同樣由 Facebook 所開源,是 GraphQL 受歡迎的原因之一,有了它就可以直接得到完整的 API 測試工具還有簡單的文件。
由上面 GraphQL Middleware 中的 graphiql: true
選項來打開。(Production 時要記得關掉)
從上面的最小範例中可以看到,Schema 中至少有必須有一個 Query
Type,裡面還可以接著放各種的 Key 以及對應的 Type,會在下面接著介紹。
GraphQL 裡面的基礎 Type (GraphQLScalarType) 有以下五種,都可以輕易的轉換成任何程式語言的值:
其他四種很容易理解,不過 ID
是怎樣的一個東西呢?看原始碼就能很清楚知道它就是任何的 Int
或 String
。
GraphQL 預設所有值可以是 null
,要避免空值的話可以在後面加上 !
來指定不能為 null
,例如:
String!
就代表不能為 null
的 String
。
List
的話則是放入 []
來表示,例如:
[Int]
不能為 null
的 List
裡面放不能是 null
的 String
就會是:
[String!]!
在 GraphQL 中,可以用 Object 的方式來形成另一個 Type,例如一個 Post
Type,裡面可以利用到前面講的所有 Type:
type Post {
id: ID!
author: String!
title: String!
body: String!
comments: [String!]!
}
ObjectType
裡面也可以再包 ObjectType
:
type User {
name: String!
}
type Post {
id: ID!
author: User!
title: String!
body: String!
comments: [String!]!
}
這樣子定義下去的話,就能漸漸的把應用程式中能查詢的 Type 都一步步的定義在 Schema 上。
在寫 GraphQL 時,我們需要清楚的知道值是什麼 Type,什麼東西可以查、什麼東西不能查。這在大架構的服務上好處特別明顯,Facebook 整個服務只有一個 GraphQL Schema 描述了所有可以查到的東西,看一下 GraphiQL 就能大致的了解 API 的內容並進行測試,非常有幫助。