👾

Next.jsにcodegenを導入した際に詰まった際の対応まとめ

2024/10/19に公開

はじめに

GaraphQL初心者のため詰まった点などをメモしておきます。
環境は以下です。

"graphql": "^16.9.0",
"@apollo/client": "^3.11.8",
"@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/client-preset": "^4.3.3",
"@parcel/watcher": "^2.4.1",

"typescript": "^5.5.4",
"next": "^14.2.8",
"react": "^18.3.1",
種別 選定技術
GraphQLクライアント Apollo Client
型生成ライブラリ GraphQL Code Generator(client-preset)
GraphQL CMS hygraph

クエリから型が出力されない場合

事象

クエリファイルからcodegen generateの出力が失敗する。

確認方法(対応方法)

ignoreNoDocumentsプロパティをfalse

基本はignoreNoDocumentsプロパティはtrueのことが多いと思いますが、falseにすることによってcodegenのwatchなどでクエリが見つからない場合はエラー文を表示し強制終了してくれます。
これによってクエリが間違っていないか、schemaが正しいか、documentsのパスがあっているかがわかります。

codegen.ts
- ignoreNoDocuments: true,
+ ignoreNoDocuments: false,

verboseプロパティを追加

上記エラーが出ても詳細が掴みづらいケースがあるため、verboseプロパティを追加することによって詳細なデバックができるようになります。

codegen.ts
+ verbose: true

このようにエラー時にbashに記載されます。

詳細
[STARTED] Parse Configuration
[SUCCESS] Parse Configuration
[STARTED] Generate outputs
[STARTED] Generate to ./src/gql/
[STARTED] Load GraphQL schemas
[SUCCESS] Load GraphQL schemas
[STARTED] Load GraphQL documents
[FAILED] 
[FAILED]       Unable to find any GraphQL type definitions for the following pointers:
[FAILED]         
[FAILED]           - src/gql/query/*.graphql
[FAILED]   

documentsプロパティのパスがgenerateのパスと同様になっていないか

以下エラーが出た際にはその可能性が高いと思われます。
恐らくは生成先のパスに対してクエリを参照しにいくことになるので循環参照的なものになっていそうですかね?

Unable to find any GraphQL type definitions for the following pointers:

その場合はdocumentsプロパティのパスとクエリファイルを格納するパスを以下のように変更する必要があります。
のパスを以下のように変更す

codegen.ts
const config: CodegenConfig = {
    schema: `https://${process.env.HYGRAPH_REGION}.cdn.hygraph.com/content/${process.env.HYGRAPH_ID}/master`,
-    documents: ['src/gql/query/*.graphql'], // クエリがある階層を識別しそこから型を生成する
+    documents: ['query/*.graphql'], // クエリがある階層を識別しそこから型を生成する

    ignoreNoDocuments: false, // watchした際にクエリが見つからない場合に終了しないように定義
    generates: {
        './src/gql/': { // 型ファイルの生成ディレクトリ
            preset: 'client',  // プリセットリストをクライアントで対応
            plugins: [],
        }
    },
    verbose: true
}

graphql拡張子ファイルのクエリを使用する

事象

クエリを記載しているファイルの拡張子がtstsxではなく、graphqlの場合どのように対応が必要なのか。

個人的に感じていた疑問点

  1. garaphqlファイルにはexportなどがないけれどどのようにimportしてpostリクエストするのか
  2. useQueryをそもそも使用するのか

確認方法(対応方法)

@graphql-codegen/typescript-react-apolloのインストール

そもそもgaraphqlファイルをtsxファイルなどと同様にimportすることはできないため、useQueryは経由せず、hooksをcodegen generateで直接的に生成する必要があります。そこでプラグインごとに役割を整理すると以下です。
そのため、別途@graphql-codegen/typescript-react-apolloをインストールする必要がありました。

プラグイン 機能
@graphql-codegen/client-preset GraphQLのクエリなどから型生成
@graphql-codegen/typescript-react-apollo GraphQLのクエリからhooksの生成

なのでcodege.tsは以下のようになり、configプロパティのwithHooks: trueを記載することでhooksを出力してくれます。

codege.ts
const config: CodegenConfig = {
    schema: `https://${process.env.HYGRAPH_REGION}.cdn.hygraph.com/content/${process.env.HYGRAPH_ID}/master`,
+   documents: ['query/*.graphql'], // クエリがある階層を識別しそこから型を生成する
    ignoreNoDocuments: false, // watchした際にクエリが見つからない場合に終了しないように定義
    generates: {
        './src/gql/': { // 型ファイルの生成ディレクトリ
            preset: 'client',  // プリセットリストをクライアントで対応
            plugins: [
+                'typescript-react-apollo',
            ],
+            config: {
+                withHooks: true,
+                withHOC: false,
+                withComponent: false,
            }
        }
    },
    verbose: true
}

export default config

上記codegen.tscodegen generateによって./src/gql/graphql.tsにhooksが出力されました。これを使用してデータが取得できました。

追記

調べたところclient-presetとplugin両方でdocumentを作成しマージし出力されるためどちらかのみにする必要があります。
client-presetのみにする場合はクエリの記述をgraphqlファイルからts,tsxファイルへ変更するのみなので割愛しますが、pluginを使用する場合は以下です。

codege.ts
const config: CodegenConfig = {
    schema: `https://${process.env.HYGRAPH_REGION}.cdn.hygraph.com/content/${process.env.HYGRAPH_ID}/master`,
    documents: ['query/*.graphql'], // クエリがある階層を識別しそこから型を生成する
    ignoreNoDocuments: false, // watchした際にクエリが見つからない場合に終了しないように定義
    generates: {
-        './src/gql/': { // 型ファイルの生成ディレクトリ
+        './src/gql/graphql.ts': { // 型ファイルの生成ディレクトリ
-           preset: 'client',  // プリセットリストをクライアントで対応
            plugins: [
+                'typescript',
+                'typescript-operations',
                 'typescript-react-apollo',
            ],
             config: {
                 withHooks: true,
                 withHOC: false,
                 withComponent: false,
            }
        }
    },
    verbose: true
}

export default config

まとめ

そもそもクエリはtsファイルなどで管理した方が良いのか、それともgaraphqlファイルで管理の方が良いのかから別途調査していきたいと思います。
恐らくはクエリ文などの見やすさの観点な気がしますが。。。

Discussion