SvelteKitでurqlとgraphql-codegen(client-preset)を使って GraphQLサーバにリクエストする
SvelteKit で urql と graphql-codegen を使って GraphQL サーバにリクエストするメモです。graphql-codegen の client-preset というのを使っています。 リクエストする GraphQL サーバは下記を使わせていただきました。
https://swapi-graphql.netlify.app/
実際に作成したリポジトリは下記です。
https://github.com/edo1z/svelte-urql-codegen-sample
SvelteKit プロジェクトの作成
npm create svelte@latest svelte-urql-codegen-samplecd svelte-urql-codegen-samplenpm i各種インストール
npm i -D @graphql-codegen/cli @graphql-codegen/client-preset @urql/svelteurql の client を使えるようにする
src/routes/+layout.svelte に下記を書きます。ルートの layout で setContextClient を実行することで、それ以外の子のコンポーネントで urql の client を getContextClient によって利用することが出来るようになります。
<script> import { createClient, setContextClient, cacheExchange, fetchExchange, } from "@urql/svelte"; const client = createClient({ url: "https://swapi-graphql.netlify.app/.netlify/functions/index", exchanges: [cacheExchange, fetchExchange], }); setContextClient(client);</script>
<slot />クエリの作成
下記ディレクトリを作成します。(このディレクトリは codegen.yml の設定次第で任意の場所・名前に変更可能です)
mkdir -p src/lib/queriessrc/lib/queries/film/GetAllFilms.tsを作成します。これは、src/lib/queries に GraphQL リクエストで使うクエリをまとめて配置する想定です。GetAllFilm.ts にGetAllFilmsというクエリを書きます。
import { graphql } from '$lib/gql/gql';
export const GetAllFilms = graphql(/* GraphQL */ ` query GetAllFilms { allFilms { totalCount films { title episodeID releaseDate } } }`);上記コードで、src/lib/gql/gqlをインポートしようとしていますが、今はありません。src/lib/gql内のファイルは、graphql-codegen によって自動作成されます。ですので、上記コードは現時点ではエラーになります。
codegen.yml の作成
プロジェクトルートに下記のcodegen.ymlを作成します。
ignoreNoDocuments: trueschema: https://swapi-graphql.netlify.app/.netlify/functions/indexdocuments: - "src/lib/queries/**/*.ts"generates: src/lib/gql/: preset: client-preset config: useTypeImports: truepackage.json の設定と graphql-codegen の実行
下記を追加することで、npm run codegen-watchを実行したら、コードの変更がある度に graphql-codegen が実行されて、codegen.yml の設定内容に従って、generatesで指定した場所に、gql.tsやgraphql.ts等が生成されます。これにより、上記で作成した GetAllFilms.ts のコードがエラーがなくなります。あとは、この GetAllFilms を urql の Client にセットして実行すれば、GraphQL リクエストができます。
"scripts": { "codegen-watch": "graphql-codegen --watch"},GraphQL にリクエストする
src/routes/+page.svelteで、GraphQL リクエスト(GetAllFilms)をして、レスポンス内容を表示させてみます。
<script> import { getContextClient, queryStore } from "@urql/svelte"; import { GetAllFilms } from "$lib/queries/film/GetAllFilms";
const filmsStore = queryStore({ client: getContextClient(), query: GetAllFilms, });</script>
<h1>Films</h1>{#if $filmsStore.fetching} <p>LOADING...</p>{:else if $filmsStore.error} <p>ERROR! {$filmsStore.error.message}</p>{:else if $filmsStore.data?.allFilms?.films} <ul> {#each $filmsStore.data.allFilms.films as film} {#if film} <li> {film.title} - Episode {film.episodeID} - Released on {film.releaseDate} </li> {/if} {/each} </ul>{:else} <p>NO films found.</p>{/if}表示内容
こんな感じで表示されます。
