UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【GraphQL】Fragment Colocation

Quramyさんの発表資料でGraphQLのFragment Colocationを知った

speakerdeck.com

GraphQLはほとんど使ったことがなかったので、データフェッチ周りの効率性をあげる有用な機能を知ることができてよかった

フロントエンドのデータフェッチ周りの問題

フロントエンドのデータフェッチ周りは、主に2つのやり方が考えられるが、それぞれメリットデメリットがある

やり方 パフォーマンス メンテナンス
コンポーネントのRootでデータを取得 通信回数が1回で済む Leafまで渡す手間があるのと、改修範囲が大きい
コンポーネントLeafでデータを取得 通信回数が多くなる、ウォーターフォール問題やN+1問題に 改修範囲が局所的

Fragment Colocation はこのトレードオフを解消する機能

大まか流れ

データフェッチプロセスを「宣言」と「実行」に分ける

Leafで宣言した情報を集約してクエリにする

書き方

Leafでまず必要とするデータを宣言する

import { FragmentType, useFragment } from './gql/fragment-masking'
import { graphql } from '../src/gql'

const fragment = graphql(/* GraphQL */ `
  fragment UserAvatar_User on User {
    name
    avatarUrl
  }
`)

const UserAvatar = (props: {
  film: FragmentType<typeof fragment>
}) => {
  const user = useFragment(fragment, props.user);
  return (<img src={user.avatarUrl} alt={user.name} />);
}

そして親コンポーネントで、上で宣言したFragmentを使用するようにする

const fragment = graphql(`
   fragment PostSummary_Post on Post {
    id
    title
    author {
       name
       ...UserAvatar_User
    }
  }
`);

注意すること

  • このColocationの特徴を活かすには、fragmentの定義はコンポーネントコード上にあるとわかりやすいため、queryやfragmentだけ別ファイルにする構成はやめるべき
  • コンポーネントが必要とするデータをfragmentで宣言するので、コンポーネントが必要とするデータの型はSchemaが提供する型ではなくfragmentの型を参照するべき