進化し続けるWeb開発の分野において、GraphQLは従来のREST APIに代わる強力な選択肢として登場し、クライアントが必要なデータを正確に要求する能力を提供しています。しかし、この柔軟性は、特にフロントエンドとバックエンド間の型安全性を維持する際に、新たな一連の課題をもたらす可能性があります。ここで登場するのが、graphql-codegenです。これは、GraphQLスキーマから型付けされたコードの生成を自動化し、開発ワークフローを大幅に強化し、実行時エラーのクラス全体を排除する革新的なツールです。
この記事は、graphql-codegenを理解し、マスターするためのガイドとして機能します。まず基本的な概念から始め、ツールのセットアップと構成の実践的で段階的な例を順に説明し、プロジェクトに統合するためのベストプラクティスを探ります。このガイドの終わりまでに、graphql-codegenを活用して、より堅牢で保守性が高く、型安全なアプリケーションを構築するための準備が整います。
最大限の生産性で開発チームが連携するための統合されたオールインワンプラットフォームをお探しですか?
Apidogはあなたのすべての要求に応え、Postmanをはるかに手頃な価格で置き換えます!
graphql-codegenとは何か、そしてなぜそれが必要なのか?
graphql-codegenの核心は、GraphQLスキーマとGraphQL操作(クエリ、ミューテーション、サブスクリプション)をイントロスペクトし、様々な言語でコードを生成するコマンドラインツールです。この初心者向けガイドでは、その最も一般的なユースケースである、フロントエンドアプリケーション向けのTypeScriptの型とフックの生成に焦点を当てます。
graphql-codegenが解決する主な問題は、GraphQL APIのデータ構造とクエリの結果に対するTypeScriptインターフェースを手動で記述するという、面倒でエラーが発生しやすいプロセスです。これがない場合、開発者は型付けされていないデータで作業するか(TypeScriptの利点を失う)、またはAPIの進化に伴って簡単に古くなる可能性のある型を作成および維持するためにかなりの時間を費やすしかありません。
graphql-codegenを採用することの利点は多岐にわたります。
- エンドツーエンドの型安全性:スキーマから直接型を生成することで、
graphql-codegenはフロントエンドコードがバックエンドのデータモデルと常に同期していることを保証します。これは、型関連のエラーを実行時ではなく、コンパイル時に捕捉できることを意味します。 - 開発者エクスペリエンスの向上:生成された型を使用すると、コードエディタでのオートコンプリートやインテリジェントな提案などの機能が利用でき、開発がより迅速かつ効率的になります。APIレスポンスの形状を推測する必要はもうありません!
- ボイラープレートの削減:
graphql-codegenは、型だけでなく、Apollo ClientやReact Queryのような一般的なGraphQLクライアント向けのすぐに使えるフックも生成できます。これにより、繰り返し発生するデータフェッチロジックを記述する必要がなくなります。 - 保守性の向上:APIスキーマが変更された場合、型を再生成するために必要なのは簡単なコマンドだけです。これにより、コードベースの保守とリファクタリングが時間とともに大幅に容易になります。
このアプローチは、「スキーマファースト」開発哲学と完全に一致します。この哲学では、GraphQLスキーマがAPIの唯一の信頼できる情報源として機能します。
はじめに:最初のgraphql-codegenセットアップ
graphql-codegenの使用に関する実践的な側面に深く入り込みましょう。このチュートリアルでは、GraphQL、TypeScriptの基本的な理解があり、Node.jsとパッケージマネージャー(npmやyarnなど)がインストールされていることを前提としています。
私たちの目標は、ブログ投稿のリストを表示するシンプルなReactアプリケーションのためにgraphql-codegenをセットアップすることです。
ステップ1:プロジェクトの初期化と依存関係
まず、TypeScriptを使用して新しいReactプロジェクトを作成し、必要な依存関係をインストールしましょう。Bash
npx create-react-app my-blog --template typescript
cd my-blog
npm install @apollo/client graphql
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset typescript
ここにインストールした依存関係の内訳を示します。
@apollo/client:React用の一般的なGraphQLクライアント。graphql:Apollo Clientとgraphql-codegenの両方に必要なピア依存関係。@graphql-codegen/cli:graphql-codegenのコマンドラインインターフェース。@graphql-codegen/client-preset:クライアントサイドアプリケーションの構成を簡素化するモダンで合理化されたプリセット。typescript:TypeScriptコンパイラ。
ステップ2:graphql-codegen初期化ウィザード
graphql-codegenを始める最も簡単な方法は、初期化ウィザードを使用することです。プロジェクトのルートディレクトリで次のコマンドを実行します。Bash
npx graphql-codegen init
ウィザードは、プロジェクトの構成を支援するために一連の質問をします。ブログアプリケーションのシナリオにおける一般的な回答のセットは次のとおりです。
- どのような種類のアプリケーションを構築していますか?
Application built with React - スキーマはどこにありますか? GraphQL APIエンドポイントのURLを提供します。このチュートリアルでは、公開されているサンプルAPIを使用できます:
https://swapi-graphql.netlify.app/.netlify/functions/index - 操作とフラグメントはどこにありますか?
src/**/*.tsx(これは、srcディレクトリ内のすべての.tsxファイルでGraphQLクエリを探すようにgraphql-codegenに指示します)。 - プラグインを選択してください:ウィザードは一連のプラグインを提案します。
typescript、typescript-operations、typescript-react-apolloを含むデフォルトは素晴らしい出発点です。 - 出力をどこに書き込みますか?
src/gql/(これにより、生成されたファイルを保存するための新しいディレクトリsrc/gqlが作成されます)。 - イントロスペクションファイルを生成しますか?
Yes(これはローカル開発やIDE拡張機能に役立ちます)。 - 設定ファイルの名前は何にしますか?
codegen.ts - package.jsonのどのスクリプトでcodegenを実行しますか?
codegen
これらの質問に回答すると、ウィザードはプロジェクトのルートにcodegen.tsファイルを作成し、package.jsonにcodegenスクリプトを追加します。
ステップ3:設定ファイル(codegen.ts)の理解
codegen.tsファイルは、graphql-codegenセットアップの中心です。ウィザードが生成する簡略化されたバージョンを見てみましょう。TypeScript
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://swapi-graphql.netlify.app/.netlify/functions/index",
documents: "src/**/*.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: []
}
}
};
export default config;
主な設定オプションを分解してみましょう。
overwrite: true:これにより、コマンドを実行するたびに既存の生成済みファイルが上書きされることが保証されます。schema:これはGraphQLスキーマのソースを指します。ライブエンドポイントのURL、ローカルの.graphqlまたは.jsonファイルなどが指定できます。documents:これは、GraphQL操作(クエリ、ミューテーション、フラグメント)を見つける場所をgraphql-codegenに伝えるグロブパターンです。generates:これは構成の最も重要な部分です。各キーが出力ファイルまたはディレクトリを表し、値が何を生成するかを定義するオブジェクトです。preset: "client":client-presetは、フロントエンドアプリケーション向けにgraphql-codegenを構成するための強力で推奨される方法です。いくつかのプラグインをバンドルし、合理化されたエクスペリエンスを提供します。クエリを記述するために使用するgraphql関数を生成します。
ステップ4:最初のGraphQLクエリの記述
graphql-codegenが構成されたので、ブログ投稿をフェッチするGraphQLクエリを記述しましょう。新しいファイルsrc/components/Posts.tsxを作成します。TypeScript
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
const GET_POSTS = gql(`
query GetPosts {
allFilms {
films {
id
title
director
releaseDate
}
}
}
`);
const Posts = () => {
const { loading, error, data } = useQuery(GET_POSTS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
{data?.allFilms?.films?.map((film) => (
<div key={film?.id}>
<h2>{film?.title}</h2>
<p>Director: {film?.director}</p>
<p>Release Date: {film?.releaseDate}</p>
</div>
))}
</div>
);
};
export default Posts;
生成されたsrc/gql/gql.tsファイルからgql関数をインポートしていることに注意してください。これはclient-presetによって提供されるgql関数であり、型推論の魔法を可能にするものです。
ステップ5:graphql-codegenの実行と魔法を見る
次に、package.jsonからcodegenスクリプトを実行します。Bash
npm run codegen
このコマンドはスキーマをイントロスペクトし、GET_POSTSクエリを見つけ、対応するTypeScriptの型をsrc/gqlディレクトリに生成します。
これで、Posts.tsxのuseQueryフックによって返されるdataオブジェクトを調べると、完全に型付けされていることがわかります!IDEはdata.allFilms.filmsのオートコンプリートを提供し、TypeScriptはクエリに存在しないフィールドにアクセスしようとすると警告を表示します。
より深く掘り下げる:実践的なブログフロントエンドの例
理解を深めるために、例を拡張しましょう。私たちのブログがより伝統的なスキーマを持っていると想像してください。GraphQL
type Author {
id: ID!
name: String!
}
type Post {
id: ID!
title: String!
content: String!
author: Author!
}
type Query {
posts: [Post!]!
post(id: ID!): Post
}
type Mutation {
createPost(title: String!, content: String!, authorId: ID!): Post!
}
このスキーマがhttp://localhost:4000/graphqlで実行されていると仮定しましょう。それに応じてcodegen.tsを更新します。TypeScript
// codegen.ts
// ...
schema: "http://localhost:4000/graphql",
// ...
次に、単一の投稿を表示するコンポーネントと、新しい投稿を作成する別のコンポーネントを作成しましょう。
単一の投稿をフェッチするTypeScript
// src/components/Post.tsx
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
import { useParams } from 'react-router-dom';
const GET_POST = gql(`
query GetPost($id: ID!) {
post(id: $id) {
id
title
content
author {
id
name
}
}
}
`);
const Post = () => {
const { id } = useParams<{ id: string }>();
const { loading, error, data } = useQuery(GET_POST, {
variables: { id },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
<h2>{data?.post?.title}</h2>
<p>By {data?.post?.author?.name}</p>
<p>{data?.post?.content}</p>
</div>
);
};
export default Post;
npm run codegenを実行すると、GetPostQueryとその変数の型が生成され、useQueryフックとその結果に型安全性が提供されます。
新しい投稿を作成するTypeScript
// src/components/CreatePost.tsx
import { gql } from '../gql/gql';
import { useMutation } from '@apollo/client';
import { useState } from 'react';
const CREATE_POST = gql(`
mutation CreatePost($title: String!, $content: String!, $authorId: ID!) {
createPost(title: $title, content: $content, authorId: $authorId) {
id
}
}
`);
const CreatePost = () => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [createPost, { data, loading, error }] = useMutation(CREATE_POST);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
createPost({ variables: { title, content, authorId: '1' } }); // Assuming authorId '1' for simplicity
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<textarea
placeholder="Content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create Post'}
</button>
{error && <p>Error creating post: {error.message}</p>}
{data && <p>Post created with ID: {data.createPost.id}</p>}
</form>
);
};
export default CreatePost;
ここでは、graphql-codegenがCreatePostMutationとその変数の型を生成します。これにより、createPost関数を呼び出す際に、title、content、authorIdに正しい型を渡すことが保証されます。
高度な概念とベストプラクティス
graphql-codegenに慣れてくると、より高度な機能やベストプラクティスに出会うでしょう。
フラグメント:graphql-codegenはGraphQLフラグメントを優れたサポートしています。.tsxファイルでフラグメントを定義でき、graphql-codegenは型を正しく処理し、コンポーネントの再利用可能で併置されたデータ依存関係を促進します。
.graphqlファイルの使用:関心の分離を向上させるために、GraphQLクエリ、ミューテーション、フラグメントを専用の.graphqlファイルに記述できます。codegen.tsのdocuments配列を更新して、このファイル拡張子を含めるだけです:documents: ["src/**/*.tsx", "src/**/*.graphql"]。
カスタムスカラー:GraphQLスキーマがカスタムスカラー(例:Date、JSON)を使用している場合、型安全性を維持するために、codegen.tsファイルでそれらを対応するTypeScriptの型にマッピングできます。
ウォッチモード:シームレスな開発エクスペリエンスのために、graphql-codegenをウォッチモードで実行できます。これにより、GraphQL操作を含むファイルを保存するたびに型が自動的に再生成されます。package.jsonのcodegenスクリプトに--watchフラグを追加するだけです:"codegen": "graphql-codegen --watch"。
一般的な問題のトラブルシューティング
graphql-codegenは強力なツールですが、初心者としていくつかの一般的な問題に遭遇する可能性があります。
- 「スキーマが見つかりません」:このエラーは通常、
codegen.tsのschemaパスが間違っているか、指定されたアドレスでGraphQLサーバーが実行されていないことを意味します。 - プラグイン構成エラー:必要なすべてのプラグインがインストールされていること、および
codegen.tsでの構成が正しいことを確認してください。 graphqlピア依存関係の問題:プロジェクトにgraphqlが直接依存関係としてインストールされていることを確認してください。
結論:型安全な未来を受け入れる
graphql-codegenは単なるコード生成ツールではなく、GraphQLを使用してアプリケーションを構築する方法におけるパラダイムシフトです。自動化を受け入れ、スキーマの力を活用することで、より堅牢で保守性が高く、作業が楽しいコードベースを作成できます。
このチュートリアルは、graphql-codegenを始めるための確固たる基盤を提供しました。コアコンセプトをカバーし、実践的な例を順に説明し、ベストプラクティスに触れました。旅はここで終わりません。graphql-codegenエコシステムは広大で、さまざまなフレームワークやユースケースに対応する豊富なプラグインコレクションがあります。公式ドキュメントを探索し、さまざまなプラグインを試して、graphql-codegenがGraphQL開発ワークフローをどのように革新できるかを発見することを強くお勧めします。ハッピーコーディング!
最大限の生産性で開発チームが連携するための統合されたオールインワンプラットフォームをお探しですか?
Apidogはあなたのすべての要求に応え、Postmanをはるかに手頃な価格で置き換えます!
