0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Next × GraphQL] Fragment colocation を使用してコードの保守性を上げよう

Last updated at Posted at 2025-05-15

概要

Next.jsGraphQL を組み合わせた開発において、コードの保守性と再利用性を高める重要な手法として「Fragment colocation」があります。

この記事では、Fragment colocation とは何か、そしてどのようにして実装するかについて解説します。

Fragment colocationとは

Fragment colocation とは、GraphQLFragment をコンポーネントと同じファイル内に定義し、そのコンポーネントが必要とするデータの形を明確に示す手法です。

Fragment は再利用可能なクエリの一部分を定義するもので、これをコンポーネントと同じ場所に配置することで、コンポーネントとデータの結びつきを強くします。

Fragment colocationの利点

  1. データ依存関係の明確化:コンポーネントが必要とするデータが明確になる
  2. コード変更の局所化:コンポーネントの変更時にデータ要件も同時に更新できる
  3. オーバーフェッチの防止:コンポーネントが必要とするデータのみを取得できる
  4. 型安全性の確保:型定義が自動生成され、型エラーを事前に検出できる

その他詳細は以下の記事などをご参考ください🙋‍♂️

実装例

それでは Next.js で実装していきます。

コンポーネントとFragment定義

まず、PostContent(記事表示)コンポーネントとそれに必要なFragmentを定義します。

src/components/ui/PostContent/index.tsx
import React from 'react'
import { PostFragment } from '@/app/graphql'
import styles from './PostContent.module.css'
import BackButton from '@/components/ui/BackButton'
import MainTitle from '@/components/ui/MainTitle'
import FormattedDate from '@/components/ui/DateFormatter'
import Image from 'next/image'
import { gql } from '@apollo/client'

type PostContentProps = {
  post: PostFragment
}

export const POST_FRAGMENT = gql`
  fragment post on Post {
    title
    content
    thumbnailUrl
    createdAt
  }
`

export default function PostContent({ post }: PostContentProps) {
  return (
    <article className={styles.container}>
      <div className={styles.header}>
        <BackButton>
          ← 戻る
        </BackButton>
        <MainTitle>{post.title}</MainTitle>
        <FormattedDate date={post.createdAt} />
      </div>

      {post.thumbnailUrl && (
        <div className={styles.thumbnailContainer}>
          <Image
            src={post.thumbnailUrl}
            alt={post.title}
            fill
            className={styles.thumbnail}
            priority
            unoptimized={true}
          />
        </div>
      )}

      <div className={styles.content}>
        {post.content}
      </div>
    </article>
  )
}
  • POST_FRAGMENTという名前で Fragment を定義し、エクスポートしています
  • Fragment には記事表示に必要な最小限のフィールドを含める
    • title, content, thumbnailUrl, createdAt
  • コンポーネントの props の型として PostFragment を使用
    • Codegen によって、自動生成された型

クエリでのFragmentの使用

次に、このFragmentを実際のクエリで使用します:

src/graphql/queries/getPost.ts
import { gql } from '@apollo/client';
import { POST_FRAGMENT } from '@/components/ui/PostContent/index';

export const GET_POST = gql`
  query GetPost($id: ID!) {
    ${POST_FRAGMENT}
    published {
      post(id: $id) {
        ...postFragment
      }
    }
  }
`;
  • コンポーネントからエクスポートされたPOST_FRAGMENTをインポートしています
  • クエリ内で Fragment を参照するために${POST_FRAGMENT}Fragment の定義を含める
  • ...postFragmentFragment を展開しています

まとめ

便利ですね。
特に、型安全の保証、実装変更時の保守性の向上はかなり恩恵があるので、積極的に活用していきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?