📡 GraphQLリクエストモジュール
Nuxt.jsと簡単に統合できる最小限のGraphQLクライアントです。
機能
- 最もシンプルで軽量なGraphQLクライアント。
- PromiseベースのAPI(
async
/await
で動作)。 - TypeScript対応。
- AST対応。
- GraphQLローダー対応。
セットアップ
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>
ストアアクション
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()
は、3番目のパラメーターとしてヘッダーオブジェクトを受け入れます
<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環境では、AbortControllerはバージョンv14.17.0以降でサポートされています。Node.js v12の場合は、abort-controllerポリフィルを使用できます。
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,
},
});
FAQ
@nuxtjs/apollo
ではなく、なぜnuxt-graphql-request
を使用するのですか?
誤解しないでください。Apollo Clientは素晴らしいもので、vue / nuxtコミュニティによって適切にメンテナンスされています。graphql-requestに切り替える前に、18か月間Apollo Clientを使用していました。
しかし、私はパフォーマンスにこだわっているので、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
をインストールする必要はありません。ただし、JSであってもTSタイプを認識するIDE(VSCodeなど)を使用している場合は、開発中に強化されたタイプセーフティの恩恵を受けることができるように、graphql
をインストールすることをお勧めします。
GraphQLドキュメントをgraphql-request
によってエクスポートされたgql
テンプレートでラップする必要がありますか?
いいえ。それは便宜上のもので、prettierフォーマットや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
を使用して開発サーバーを起動する
ロードマップ
- WebSocketクライアントをサポートしますか?
- 型付きGraphql-requestクライアントを生成する