一、為什麼前端開發者該認識 GraphQL
做過前後端分離的同學一定有過這種經驗:一個頁面要顯示使用者資料、訂單清單、商品評論,於是前端連續打了三、四支 REST API,每一支都帶回一大包用不到的欄位,卻還得自己在前端拼裝;更慘的是,行動網路弱的地方,多餘的資料量直接拖慢了載入速度。
GraphQL 就是為了解決這類「拿太多」或「拿不夠」的痛點而生的。它用單一個端點(通常是 /graphql),讓前端用一份查詢語句(Query)精準聲明「我只要這些欄位」,後端就只回傳你點名的資料。就像走進點菜式火鍋店,你勾什麼就拿什麼,而不是端來一整鍋。
二、GraphQL 與 REST 的核心差異
- 端點數量:REST 通常一種資源一個 URL(/users、/orders);GraphQL 只有一個端點,靠查詢內容區分意圖。
- 回傳結構:REST 回傳後端定死的欄位;GraphQL 回傳前端要的欄位,不多不少。
- 過度獲取與欠獲取:REST 容易一次拿太多或要打好幾次;GraphQL 一次查詢就能組合多種資源。
- 型別系統:GraphQL 內建 Schema 與型別定義,前後端合約清清楚楚,開發體驗類似一份即時更新的 API 文件。
三、實戰:用 Node.js 架一個最小 GraphQL 服務
我們用 express 與 graphql-http 快速搭一個可跑的範例。先安裝相依:
npm init -y
npm install express graphql graphql-http
步驟 1:定義資料與 Schema。下面是極簡的「書籍」查詢:
const { buildSchema } = require('graphql');
const schema = buildSchema(`
type Book {
id: ID
title: String
author: String
}
type Query {
book(id: ID!): Book
books: [Book]
}
`);
const books = [
{ id: '1', title: 'GraphQL 實戰', author: 'Edwin' },
{ id: '2', title: '前端進化論', author: 'Weilong' },
];
const root = {
book: ({ id }) => books.find(b => b.id === id),
books: () => books,
};
步驟 2:掛載 GraphQL 端點並啟動伺服器:
const express = require('express');
const { createHandler } = require('graphql-http/lib/use/express');
const app = express();
app.all('/graphql', createHandler({ schema, rootValue: root }));
app.listen(4000, () => console.log('GraphQL 跑在 http://localhost:4000/graphql'));
步驟 3:用前端發送查詢。注意我們只索取 title 與 author,id 與其他潛在欄位都不會出現:
const query = `
query {
book(id: "1") {
title
author
}
}
`;
fetch('http://localhost:4000/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
})
.then(r => r.json())
.then(data => console.log(data.data.book));
四、變更資料:Mutation 與變數
讀取用 Query,寫入(新增、修改、刪除)則用 Mutation。搭配變數可以讓查詢語句保持乾淨、避免字串拼接的注入風險:
const mutation = `
mutation AddBook($title: String!, $author: String!) {
addBook(title: $title, author: $author) {
id
title
}
}
`;
// 變數透過 variables 欄位傳入
fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: mutation,
variables: { title: '新書', author: '海晏' },
}),
});
五、在前端專案中落地的小建議
- 重點:複雜專案建議搭配
Apollo Client或urql,它們內建快取、錯誤處理與開發者工具,能大幅減少樣板程式碼。 - npm 套件版本要對齊 Node.js 版本;若部署環境只支援 PHP(如虛擬主機),前端可將 GraphQL 當作「純查詢層」呼叫遠端服務,後端另行部署。
- Schema 是第一公民,記得把型別定義當成團隊契約來維護,必要時導入程式碼生成(codegen)自動產生 TypeScript 型別。
互動話題:你在專案裡是 REST 派還是 GraphQL 派?遇過最棘手的「過度獲取」問題是什麼?歡迎在留言區分享你的經驗!