※ 什麼是GraphQL?
GraphQL 是由 Facebook 於 2015 年開發的一種 API 查詢語言。客戶端(前端)只會接收到所需的數據,減少了不必要的數據傳輸和多次請求的需要,提高了應用程序的性能和效率。GraphQL 支持查詢、變更和即時更新操作,解決了傳統 REST API 中的因回傳整個數據結構導致流量變多處理時間變長,或需要多次請求才能獲取所有所需的訊息,增加了延遲和複雜性的問題。GraphQL作為一種標準,定義了如何查詢和操作數據,並提供了規範和指南,幫助開發者設計和使用 GraphQL API。
GraphQL 的主要特點包括:
- 查詢(Query):從伺服器獲取資料,開發者可以在查詢中指定所需的資料欄位,伺服器將按照指定的結構返回相應的資料。
- 變更(Mutation):在伺服器上修改資料,例如新增、更新或刪除資料。
- 訂閱(Subscription):用於伺服器上的即時資料更新。當資料發生變化時,伺服器會主動推送相關的更新給訂閱者。
※ 客戶端(前端)所需要的數據有哪些:
- 用戶數據:包括用戶的個人資訊、登入憑證、偏好設定。
- 產品數據:例如電子商務應用中的產品名稱、價格、描述、庫存狀況等。
- 交易數據:例如購物車內容、訂單詳情、付款資訊等。
- 內容數據:例如部落格文章、新聞報導、評論、圖片和影片等。
- 地理數據:例如位置座標、地址、地圖資料等。
- 分析數據:包括用戶行為分析、流量統計、轉換率等。
※ GraphQL所需要的工具:
- 終端機(Terminal):使用者可以輸入各種命令來執行操作。
- 編輯器。
- 使用指令安裝GraphQL。
※ 透過Node js安裝GraphQL:
安裝指令:npm install graphql
※ 為什麼要安裝GraphQL?
GraphQL是一個多功能套件組成的一個模組,其中有許多工具來輔助幾件事情:
- 轉換Schema結構:AST(抽象語法樹)會將我們定義的 Schema 轉換成 JavaScript 可以理解的物件(object)結構。這樣可以讓我們在程式中更方便地操作和使用這些資料。
★補充說明
GraphQL Schema 定義語言(SDL)的標準寫法:
type User {
id: ID!
name: String!
email: String!
age: Int
}
type Query{
user: User
}
type User
定義了一個名為User
的類型,包含id
、name
、email
和age
這些欄位。type Query
定義了一個查詢類型,包含一個user
欄位,返回User
類型的資料。

- 使用與配置型別:在 GraphQL 中,使用 Schema 定義語言(SDL)來定義數據的結構和型別。這些型別可以是內建的標量型別(如
String
、Int
、Float
等),也可以是自訂的物件型別。透過這些型別,我們可以精確地描述 API 的數據結構,並使用解析函數(Resolver)來處理查詢和變更請求,返回相應的數據或錯誤訊息。

★ 補充說明
開端(Schema)– GraphQLSchema介紹:
GraphQLSchema 是 GraphQL 的核心部分,程式碼由此開始寫。它用來定義資料的結構,包括:
- 類型(Types):描述資料的形狀和屬性。
- 查詢(Queries):定義客戶端可以用來獲取資料的操作。
- 變更(Mutations):定義客戶端可以用來修改資料的操作。
- 訂閱(Subscriptions):允許客戶端訂閱資料變更的即時更新。
這些元素共同構成了 GraphQL API,使得客戶端能夠靈活地查詢和操作數據。
★ 建立一個基本的 GraphQL schema架構:
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
user: {
type: GraphQLString
}
}
}),
})

★ 補充說明
- 在 GraphQL 中,預設類型(Scalars) 是用來表示基本的數據類型。這些類型幫助我們定義和驗證從客戶端到伺服器之間傳輸的數據。GraphQL 預設提供了以下幾種 scalar 類型:
- GraphQLInt:32 位元的有符號整數。
- GraphQLFloat:雙精度浮點數,通常用於需要表示精確數值的情況。
- GraphQLString:UTF-8 字符串。
- GraphQLBoolean:布林值(true 或 false)。
- GraphQLID:唯一標識符,通常用於標識對象。
- 使用 Scalars Type 時,記得要加上
type
是因為這樣可以明確地定義字段的數據類型。這有助於確保從客戶端到伺服器之間傳輸的數據具有一致性和正確性。
★ 建立一個使用 Scalars Type 時,記得要加上 type的
架構:
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
email: { type: GraphQLString }
}
});
★ 補充說明
在 GraphQL 中,定義類型是用來描述 API 中的數據結構和它們之間的關係。這些定義類型告訴我們可以查詢哪些數據、這些數據的結構是什麼樣的,以及可以對這些數據進行哪些操作。以下是一些具體的定義類型及其作用:
- 物件類型(GraphQLObjectType):
- 描述實體及其欄位。
- 例如,一個
User
類型可能包含id
、name
和email
欄位。
const UserType = new GraphQLObjectType({
interfaces: [DateTimeInterface],
name: 'User',
fields: {
id: {
type: GraphQLNonNull(GraphQLID)
},
name: {
type: GraphQLString
},
email: {
type: GraphQLString
},
}
});
- 標量類型(GraphQLScalarType):
- 表示基本數據類型,如
Int
、Float
、String
、Boolean
和ID
。 - 這些類型用來表示簡單的值。
★ 建立一個基本的 GraphQLScalarType架構:
// 定義 DateType日期類型
const DateType = new GraphQLScalarType({
name: 'Date',
parseValue(value) {
return new Date(value)
},
serialize(value) {
return value.getTime()
}
});
- 輸入類型(GraphQLInputObjectType):
GraphQLInputObjectType 是用來定義輸入參數的結構。當你在mutation中需要傳遞複雜的參數時,可以使用GraphQLInputObjectType來定義這些參數的結構。
當 GraphQL 中需要新增、更新或刪除資料時,會使用 mutation
作為改變資料的操作入口點。這與查詢資料的 query
不同,query
是用來查詢資料的。為了避免在數據修改時出現錯誤的數據輸入,可以使用 GraphQLInputObjectType
來定義輸入參數的結構。
GraphQLInputObjectType
的作用是:
- 定義輸入參數結構:用來描述在
mutation
中需要傳遞的複雜參數。 - 確保數據完整性:避免在數據修改時出現錯誤的數據輸入。
★ 建立一個基本的 GraphQLInputObjectType架構:

- 枚舉(列舉)類型(GraphQLEnumType):
Enum(枚舉或列舉)是一種用來定義一組固定選項的類型,這些選項是預先定義好的,不能隨意更改。在 GraphQL 中,枚舉類型可以幫助確保數據的一致性和完整性,因為它限制了欄位只能接受特定的值,避免錯誤的數據輸入,並使 API 更加自描述和易於理解。
查詢枚舉類型的欄位時,返回的值通常會以字串(string)的形式表示,因為枚舉的每個選項本質上都是一個有名字的固定值(具名的常量)。這些常量在查詢結果中會被轉換成對應的字串。
在狀態機(State Machine)中,我們可以使用枚舉來表示不同的狀態,例如 stop
、processing
和 completed
。枚舉可以將這些狀態代換為一個數字(例如 0、1、2),這樣我們可以更方便地進行狀態的比較和處理。枚舉提供了名稱和值的對應關係,使我們能夠將數字轉換為看得懂的字串,更好的認出當前狀態。
總結來說,Enum可以幫助我們將複雜的狀態或選項轉換成更簡單且易於閱讀的形式。這樣,我們在回傳數據時,可以提供更容易理解的資訊。

★ 建立一個基本的 GraphQLEnumType架構:
const WorkStateType = new GraphQLEnumType({
name: 'WorkState',
values: {
STOP: {
value: 0
},
COMPLETED: {
value: 1
}
}
})
在這個例子中,WorkStateType
定義了兩個固定的選項:STOP
和 COMPLETED
,分別對應數值 0
和 1
。這樣可以確保在使用 WorkStateType
的欄位中,只能接受這兩個預定義的值。
- 介面類型(GraphQLInterfaceType):
- 介面(Interface)可以幫助我們定義一組共同欄位,並讓多個物件類型實現,進而統一查詢語法,簡化數據查詢。
★ 建立一個基本的 GraphQLInterfaceType架構:
const DateTimeInterface = new GraphQLInterfaceType({
name: 'DateTimeInterface',
fields: {
created_at: {
type: DateType
},
updated_at: {
type: DateType
}
}
})
在這個例子中,DateTimeInterface
介面定義了 created_at
和 updated_at
這兩個共同欄位。然後,其他物件類型例如User
類型或查詢時可以實現這個介面,並且各自添加特有的欄位。

※ 使用 GraphQLList 來定義 GraphQL 架構中的對象列表:
GraphQLList 是 GraphQL 中的一種類型包裝器,用來表示某一類型的列表。當你需要使用陣列類型時,可以使用 GraphQLList 來包裝該類型,這樣就能夠定義和處理該類型的陣列。
★ 建立一個使用 GraphQLList 來包裝一個特定類型架構:
friends: {
type: GraphQLList(GraphQLString) // ['Tom', 'Bob', 'Ray']
}
這段程式碼定義了一個名為 friends
的欄位,其類型為 GraphQLList(GraphQLString)
。這表示 friends
欄位的值是一個字符串(String)類型的陣列,例如 ['Tom', 'Bob', 'Ray']
。

※ 使用 GraphQLNonNull 可以確保某個欄位參數或回椽值必須有一個有效的值,不能是 null。

※ 介紹 一個工具函數 – buildSchema。
什麼是buildSchema (建立模式)?
用來簡化定義 GraphQL schema 的過程。它允許你使用一個簡單的字符串語法來定義 schema,大大簡化撰寫 schema 的過程。


- 執行查詢描述並且給予結果或錯誤訊息:在 GraphQL 中,開發者可以自訂查詢和變更的內容。當發生錯誤或收到不符合預期的訊息時,GraphQL 會自動回覆標準化的錯誤訊息,讓前端知道這些訊息是從後端來的,並且經過規範處理。這樣可以確保錯誤訊息是可預期的,並且有助於調試和維護應用程式。