こんにちは!SvelteKitはREST APIとの統合が得意ですが、GraphQLを使うことで、さらに柔軟で効率的なデータフェッチングが可能です。この記事では、SvelteKitとurqlライブラリを使って、GraphQL APIからブログ記事を取得する方法を解説します。コード例を交えながら、シンプルで型安全なデータ取得を体験しましょう!
なぜGraphQLか?
GraphQLは、必要なデータだけをリクエストできるAPI仕様で、以下のような利点があります:
- 柔軟性:クライアントが必要なフィールドだけを指定。
- 型安全:スキーマベースで、TypeScriptとの相性が良い。
- 単一エンドポイント:複数のRESTエンドポイントを管理する必要なし。
SvelteKitでGraphQLを使うと、urqlのような軽量ライブラリで簡単にデータフェッチングができます。ReactのApollo Clientに比べ、urqlは設定がシンプルで、SvelteKitの軽快な開発体験にマッチします。
プロジェクトのセットアップ
新しいSvelteKitプロジェクトを作成:
npm create svelte@latest graphql-blog
cd graphql-blog
npm install
urqlと関連パッケージをインストール:
npm install @urql/svelte graphql
Skeleton UIを追加:
npm install @skeletonlabs/skeleton @skeletonlabs/tw-plugin --save-dev
この記事では、GraphQL Hiveのような公開GraphQL APIを仮に使用しますが、実際には自分のバックエンド(例:Hasura)を推奨します。
GraphQLの統合
1. urqlクライアントの設定
src/lib/graphql-client.ts
を作成:
import { createClient, defaultExchanges } from '@urql/svelte';
export const client = createClient({
url: 'https://api.graphqlhive.com/graphql', // 仮のGraphQLエンドポイント
exchanges: defaultExchanges
});
-
解説:
-
createClient
でGraphQLエンドポイントを設定。 -
defaultExchanges
でキャッシュやフェッチングを有効化。
-
2. ブログ記事の取得
ブログ記事を取得するクエリを定義。src/lib/queries.ts
:
import { gql } from '@urql/svelte';
export const GET_POSTS = gql`
query GetPosts {
posts {
id
title
slug
excerpt
createdAt
}
}
`;
export const GET_POST = gql`
query GetPost($slug: String!) {
post(slug: $slug) {
id
title
slug
excerpt
content
createdAt
}
}
`;
3. ブログ一覧ページの実装
src/routes/+page.svelte
を更新:
<script>
import { operationStore, query } from '@urql/svelte';
import { GET_POSTS } from '$lib/queries';
import { Card, CardHeader, CardContent, CardFooter, Spinner } from '@skeletonlabs/skeleton';
const posts = operationStore(GET_POSTS);
query(posts);
</script>
<div class="container mx-auto p-8">
<h1 class="h1 mb-8">ブログ記事一覧</h1>
{#if $posts.fetching}
<div class="flex justify-center">
<Spinner />
</div>
{:else if $posts.error}
<p class="text-error-500">エラー: {$posts.error.message}</p>
{:else}
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
{#each $posts.data.posts as post}
<Card>
<CardHeader>
<h2 class="h3">{post.title}</h2>
<p class="text-sm text-surface-500">{post.createdAt}</p>
</CardHeader>
<CardContent>
<p>{post.excerpt}</p>
</CardContent>
<CardFooter>
<a href="/blog/{post.slug}" class="btn variant-filled-primary">続きを読む</a>
</CardFooter>
</Card>
{/each}
</div>
{/if}
</div>
4. 記事詳細ページの実装
src/routes/blog/[slug]/+page.svelte
を作成:
<script>
import { operationStore, query } from '@urql/svelte';
import { GET_POST } from '$lib/queries';
import { Spinner, Card } from '@skeletonlabs/skeleton';
export let data;
const post = operationStore(GET_POST, { slug: data.slug });
query(post);
</script>
<svelte:head>
{#if !$post.fetching && !$post.error}
<title>{$post.data.post.title} | My Blog</title>
<meta name="description" content={$post.data.post.excerpt} />
{/if}
</svelte:head>
<div class="container mx-auto p-8">
{#if $post.fetching}
<div class="flex justify-center">
<Spinner />
</div>
{:else if $post.error}
<p class="text-error-500">エラー: {$post.error.message}</p>
{:else}
<Card class="p-6">
<header class="mb-4">
<h1 class="h2">{$post.data.post.title}</h1>
<p class="text-sm text-surface-500">{$post.data.post.createdAt}</p>
</header>
<section class="prose">
<p>{$post.data.post.content}</p>
</section>
<footer class="mt-6">
<a href="/" class="btn variant-ghost-primary">一覧に戻る</a>
</footer>
</Card>
{/if}
</div>
src/routes/blog/[slug]/+page.ts
:
export function load({ params }) {
return {
slug: params.slug
};
}
5. 動作確認
プロジェクトを起動:
npm run dev
以下のURLを試す:
-
http://localhost:5173
:GraphQLから取得した記事一覧。 -
http://localhost:5173/blog/your-slug
:記事詳細ページ。
Skeleton UIのカードデザインで、記事がモダンに表示されます。ReactのApollo Clientでは、プロバイダーの設定やキャッシュ管理が複雑ですが、urqlは軽量で、SvelteKitのストアと自然に統合されます。
やってみよう!(チャレンジ)
GraphQLのミューテーションを使って、記事を投稿するフォームを追加してみましょう!以下のようなミューテーションを定義:
export const CREATE_POST = gql`
mutation CreatePost($title: String!, $slug: String!, $excerpt: String!, $content: String!) {
createPost(title: $title, slug: $slug, excerpt: $excerpt, content: $content) {
id
title
slug
}
}
`;
src/routes/create/+page.svelte
でフォームを実装し、投稿後に一覧ページにリダイレクトしてみてください。また、urqlの@urql/exchange-graphcache
を導入して、キャッシュを自動更新する機能を試してみましょう!
まとめ
この記事では、SvelteKitとurqlを使って、GraphQL APIからブログ記事を効率的に取得しました。Skeleton UIでモダンなUIを簡単に作り、型安全なデータフェッチングを実現しました。ReactのApollo Clientと比べ、urqlは設定が少なく、SvelteKitの軽快な開発体験を最大限に活かせます。
この記事が役に立ったと思ったら、LGTMやストックしていただけると嬉しいです!GraphQLで挑戦したいことや質問があれば、コメントで教えてください。また会いましょう!