SvelteKit 環境で GraphQLを使う
SvelteKit使い始めたばっかりですが、簡潔に記述できるし、SSRがかんたんに出来たりで、とても気に入っています。
Dunning-Kruger効果的には「完全に理解した」状態ですが、学んだこと書いておきます。
やりたいこと。
バックエンドはGraphQLを開発しているので、GraphQLで定義された型、Query、Mutationをフロントで再度定義することなく利用したい。
以下のリンクを参照しながら進めます。the guildのドキュメントは再現性低くて昔から結構読みにくいです。。。
https://the-guild.dev/graphql/codegen/docs/guides/svelte
https://zenn.dev/takurinton/articles/76582f25d942f0
環境について
Ubuntu 22.04
svelte 3.54.0
@graphql-codegen/cli 2.16.4
@graphql-codegen/typescript 2.8.7
@graphql-codegen/typescript-operations 2.5.12
進め方
結果論になりますが、 svelte-apollo は解決不能なエラーが解消が出来ず、初期導入がどうしても出来ずに、諦めました。なんかバグある?
なので、@apollo/clientのインスタンスを自分で作って、CodeGenで作成されるコードから参照させる形を取りました。
Setup
# 素のアプリケーション作成
npm create svelte@latest myapp
cd myapp
npm install
# code generatorを入れる
npm install --save-dev @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations graphql-codegen-svelte-apollo
# apollo clientをいれる
npm install --save @apollo/client
以下のようにCode Generatorの設定を入れます。
schema:
- http://localhost:8080/graphql:
documents:
- ./src/**/*.gql
generates:
'./src/graphql/generated.ts':
plugins:
- typescript
- typescript-operations
- graphql-codegen-svelte-apollo
config:
clientPath: ../lib/graphql/apollo
そしてApollo ClientをdefaultでExportするファイルを作る。場所は codegen.yml
の generates.config.clientPath
と一致させます。
ついでにidTokenを更新するための関数も用意してexportしておきます。 (トークンを更新するたびにこれを呼べばOKです)
import { ApolloClient, InMemoryCache } from '@apollo/client/core/core.cjs'
import { HttpLink } from '@apollo/client/link/http/http.cjs'
const cache = new InMemoryCache()
const client = new ApolloClient({
cache,
})
const newLink = (idToken: string) => {
return new HttpLink({
uri: 'https://MY_GRAPHQL_HOST/graphql',
headers: {
Authorization: `Bearer ${idToken}`,
},
})
}
export default client
export const updateClientWithIdToken = (idToken: string) => {
const newHttpLink = newLink(idToken)
client.setLink(newHttpLink)
}
Firebase Authenticationの場合こんな感じで更新する。。。
getAuth().onAuthStateChanged(async (user) => {
if (!!user) {
const idToken = await user.getIdToken()
updateClientWithIdToken(idToken)
}
}
使ってみる
とりあえずQueryなりMutationなり書いてみる。codegen.yml
で指定した documents
で拾われる場所であればどこで置いてもいいです。
mutation SomeMutation {
someMutation {
id
uid
validUntil
createdAt
}
}
npx graphql-codegen
でコードが自動生成されますので、早速使ってみましょう。
<script lang="ts">
import { onMount } from 'svelte'
import { SomeMutation } from '../../../../graphql/generated'
import store from './store'
onMount(async () => {
const result = await SomeMutation({})
store.set(result.data?.someMutation)
})
</script>
{$store?.id} <-- こんな感じで参照する。型も自動生成されるので、IntelliSenseが効いてとても便利です。
まとめ
ドキュメントが少なすぎて環境作る際にとても苦労しましたが、それ以外はすんなり行きました。誰かの役に立てば幸いです。
フロントエンドではやっぱり型定義などはやらず、ビジネスロジックをなるべく省いてPresentation Layerの関心事だけに集中するのが好きですが、結構それに近くて気に入っています。
♥ Svelte/Kit, GraphQL