📡 GraphQL 請求模組
簡易的最小化 GraphQL 客戶端與 Nuxt.js 的整合。
特色
- 最簡單輕巧的 GraphQL 客戶端。
- 基於 Promise 的 API (適用於
async
/await
)。 - Typescript 支援。
- AST 支援。
- GraphQL Loader 支援。
設定
npx nuxi@latest module add graphql-request
對於 Nuxt2,請使用 nuxt-graphql-request v6
yarn add nuxt-graphql-request@v6 graphql --dev
nuxt.config.js
module.exports = {
modules: ['nuxt-graphql-request'],
build: {
transpile: ['nuxt-graphql-request'],
},
graphql: {
/**
* An Object of your GraphQL clients
*/
clients: {
default: {
/**
* The client endpoint url
*/
endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
/**
* Per-client options overrides
* See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
*/
options: {},
},
secondClient: {
// ...client config
},
// ...your other clients
},
/**
* Options
* See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
*/
options: {
method: 'get', // Default to `POST`
},
/**
* Optional
* default: false (this includes graphql-tag for node_modules folder)
*/
includeNodeModules: true,
},
};
執行階段設定
如果您需要在執行階段而不是建置階段提供端點,您可以使用執行階段設定來提供您的值
nuxt.config.js
module.exports = {
publicRuntimeConfig: {
graphql: {
clients: {
default: {
endpoint: '<client endpoint>',
},
secondClient: {
endpoint: '<client endpoint>',
},
// ...more clients
},
},
},
};
TypeScript
類型定義應該可以直接使用。您應該已經設定好 Typescript 以擴展 Nuxt 的自動產生設定。如果沒有,您可以從這裡開始
{
"extends": "./.nuxt/tsconfig.json"
}
用法
元件
useAsyncData
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const query = gql`
query planets {
allPlanets {
planets {
id
name
}
}
}
`;
const { data: planets } = await useAsyncData('planets', async () => {
const data = await $graphql.default.request(query);
return data.allPlanets.planets;
});
</script>
使用者定義的函式
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const query = gql`
query planets {
allPlanets {
planets {
id
name
}
}
}
`;
const planets = ref([])
const fetchPlanets = () => {
const data = await $graphql.default.request(query);
planets.value = data.allPlanets.planets;
}
</script>
Store actions
import { defineStore } from 'pinia';
import { gql } from 'nuxt-graphql-request/utils';
import { useNuxtApp } from '#imports';
type Planet = { id: number; name: string };
export const useMainStore = defineStore('main', {
state: () => ({
planets: null as Planet[] | null,
}),
actions: {
async fetchAllPlanets() {
const query = gql`
query planets {
allPlanets {
planets {
id
name
}
}
}
`;
const data = await useNuxtApp().$graphql.default.request(query);
this.planets = data.allPlanets.planets;
},
},
});
GraphQL 請求客戶端
來自官方 graphql-request 函式庫的範例。
透過 HTTP 標頭進行驗證
export default defineNuxtConfig({
graphql: {
clients: {
default: {
endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
options: {
headers: {
authorization: 'Bearer MY_TOKEN',
},
},
},
},
},
});
逐步設定標頭
如果您想在 GraphQLClient 初始化後設定標頭,您可以使用 setHeader()
或 setHeaders()
函式。
const { $graphql } = useNuxtApp();
// Override all existing headers
$graphql.default.setHeaders({ authorization: 'Bearer MY_TOKEN' });
// Set a single header
$graphql.default.setHeader('authorization', 'Bearer MY_TOKEN');
設定端點
如果您想在 GraphQLClient 初始化後變更端點,您可以使用 setEndpoint()
函式。
const { $graphql } = useNuxtApp();
$graphql.default.setEndpoint(newEndpoint);
在每個請求中傳遞標頭
可以為每個請求傳遞自訂標頭。request()
和 rawRequest()
接受標頭物件作為第三個參數
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const requestHeaders = {
authorization: 'Bearer MY_TOKEN',
};
const planets = ref();
const fetchSomething = async () => {
const query = gql`
query planets {
allPlanets {
planets {
id
name
}
}
}
`;
// Overrides the clients headers with the passed values
const data = await $graphql.default.request(query, {}, requestHeaders);
planets.value = data.allPlanets.planets;
};
</script>
將更多選項傳遞給 fetch
export default defineNuxtConfig({
graphql: {
clients: {
default: {
endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
options: {
credentials: 'include',
mode: 'cors',
},
},
},
},
});
或使用 setHeaders / setHeader
const { $graphql } = useNuxtApp();
// Set a single header
$graphql.default.setHeader('credentials', 'include');
$graphql.default.setHeader('mode', 'cors');
// Override all existing headers
$graphql.default.setHeaders({
credentials: 'include',
mode: 'cors',
});
使用 GraphQL 文件變數
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const fetchSomething = async () => {
const query = gql`
query planets($first: Int) {
allPlanets(first: $first) {
planets {
id
name
}
}
}
`;
const variables = { first: 10 };
const planets = await this.$graphql.default.request(query, variables);
};
</script>
錯誤處理
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const fetchSomething = async () => {
const mutation = gql`
mutation AddMovie($title: String!, $releaseDate: Int!) {
insert_movies_one(object: { title: $title, releaseDate: $releaseDate }) {
title
releaseDate
}
}
`;
const variables = {
title: 'Inception',
releaseDate: 2010,
};
const data = await $graphql.default.request(mutation, variables);
};
</script>
GraphQL 變更
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const fetchSomething = async () => {
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
fullname # "Cannot query field 'fullname' on type 'Actor'. Did you mean 'name'?"
}
}
}
`;
try {
const data = await $graphql.default.request(query);
console.log(JSON.stringify(data, undefined, 2));
} catch (error) {
console.error(JSON.stringify(error, undefined, 2));
process.exit(1);
}
};
</script>
接收原始回應
request
方法將會傳回回應中的 data
或 errors
金鑰。如果您需要存取 extensions
金鑰,您可以使用 rawRequest
方法
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const query = gql`
query planets($first: Int) {
allPlanets(first: $first) {
planets {
id
name
}
}
}
`;
const variables = { first: 10 };
const { data, errors, extensions, headers, status } = await $graphql.default.rawRequest(
endpoint,
query,
variables
);
console.log(JSON.stringify({ data, errors, extensions, headers, status }, undefined, 2));
批次查詢
<script setup>
const { $graphql } = useNuxtApp();
const fetchSomething = async () => {
const query1 = /* GraphQL */ `
query ($id: ID!) {
capsule(id: $id) {
id
landings
}
}
`;
const variables1 = {
id: 'C105',
};
const query2 = /* GraphQL */ `
{
rockets(limit: 10) {
active
}
}
`;
const query3 = /* GraphQL */ `
query ($id: ID!) {
core(id: $id) {
id
block
original_launch
}
}
`;
const variables3 = {
id: 'B1015',
};
try {
const data = await $graphql.default.batchRequests([
{ document: query1, variables: variables1 },
{ document: query2 },
{ document: query3, variables: variables3 },
]);
console.log(JSON.stringify(data, undefined, 2));
} catch (error) {
console.error(JSON.stringify(error, undefined, 2));
process.exit(1);
}
};
</script>
取消
可以使用 AbortController
訊號取消請求。
<script setup>
import { gql } from 'nuxt-graphql-request/utils';
const { $graphql } = useNuxtApp();
const fetchSomething = async () => {
const query = gql`
query planets {
allPlanets {
planets {
id
name
}
}
}
`;
const abortController = new AbortController();
const planets = await $graphql.default.request({
document: query,
signal: abortController.signal,
});
abortController.abort();
};
</script>
在 Node 環境中,從 v14.17.0 版本開始支援 AbortController。對於 Node.js v12,您可以使用 abort-controller polyfill。
import 'abort-controller/polyfill';
const abortController = new AbortController();
中介軟體
可以使用中介軟體來預先處理任何請求或處理原始回應。
請求 & 回應中介軟體範例 (將實際驗證權杖設定為每個請求 & 如果發生錯誤則記錄請求追蹤 ID)
function requestMiddleware(request: RequestInit) {
const token = getToken();
return {
...request,
headers: { ...request.headers, 'x-auth-token': token },
};
}
function responseMiddleware(response: Response<unknown>) {
if (response.errors) {
const traceId = response.headers.get('x-b3-traceid') || 'unknown';
console.error(
`[${traceId}] Request error:
status ${response.status}
details: ${response.errors}`
);
}
}
export default defineNuxtConfig({
modules: ['nuxt-graphql-request'],
graphql: {
/**
* An Object of your GraphQL clients
*/
clients: {
default: {
/**
* The client endpoint url
*/
endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
/**
* Per-client options overrides
* See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
*/
options: {
requestMiddleware: requestMiddleware,
responseMiddleware: responseMiddleware,
},
},
// ...your other clients
},
/**
* Options
* See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
*/
options: {
method: 'get', // Default to `POST`
},
/**
* Optional
* default: false (this includes graphql-tag for node_modules folder)
*/
includeNodeModules: true,
},
});
常見問題
為什麼要使用 nuxt-graphql-request
而不是 @nuxtjs/apollo
?
別誤會我的意思,Apollo Client 很棒,而且由 vue / nuxt 社群維護良好,我在切換到 graphql-request 之前使用了 Apollo Client 18 個月。
但是,由於我對效能非常著迷,Apollo Client 對我來說根本不適用
- 我不需要另一個狀態管理,因為 Vue 生態系統就足夠了 (Vuex & 持續資料)。
- 我不需要在我的應用程式中額外解析 ~120kb 的資料來擷取我的資料。
- 我不需要訂閱,因為我使用 pusher.com,也有 WS 客戶端的替代方案:http://github.com/lunchboxer/graphql-subscriptions-client
為什麼我必須安裝 graphql
?
graphql-request
使用來自 graphql
套件的 TypeScript 類型,這樣如果您使用 TypeScript 建置專案,而且您使用 graphql-request
但沒有安裝 graphql
,TypeScript 建置將會失敗。詳細資訊在此。如果您是 JS 使用者,那麼您實際上不需要安裝 graphql
。但是,如果您使用 IDE 來選擇 JS 的 TS 類型 (例如 VSCode),那麼安裝 graphql
仍然符合您的利益,這樣您可以在開發期間受益於增強的類型安全性。
我是否需要將我的 GraphQL 文件包裝在 graphql-request
匯出的 gql
範本中?
不需要。它是為了方便起見,讓您可以獲得工具支援,例如更漂亮的格式和 IDE 語法高亮顯示。如果因為某些原因需要,您也可以使用來自 graphql-tag
的 gql
。
graphql-request
、Apollo 和 Relay 之間有什麼區別?
graphql-request
是最簡潔且最易於使用的 GraphQL 客戶端。它非常適合小型腳本或簡單的應用程式。
與像 Apollo 或 Relay 這樣的 GraphQL 客戶端相比,graphql-request
沒有內建快取,也沒有前端框架的整合。目標是盡可能保持套件和 API 的簡潔。
nuxt-graphql-request 是否支援變更?
當然,您可以像以前一樣執行任何 GraphQL 查詢和變更 👍
開發
- 複製此儲存庫
- 使用
yarn install
或npm install
安裝相依性 - 使用
yarn dev
或npm run dev
啟動開發伺服器