【Day 7】Web環境構築 - GraphQL Code Generator

## はじめに

![スライド8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/bb1cab2a-2174-547b-0e60-c387cdce3b83.png)

---

**2023年アドベントカレンダー7日目**です。

https://qiita.com/advent-calendar/2023/life-sync-app

前回の続きで「開発者はWebの開発を進めることができる」を進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/13e79272-8479-39f1-e857-a04f2bfcc4b1.png)

## GraphQL Code Generator

### GraphQL Code Generatorとは

https://the-guild.dev/graphql/codegen

### Install

```bash:web/
npm i graphql
npm i -D typescript @graphql-codegen/cli
```

initコマンドが用意されているのでそれを使用してみます。

```bash
npx graphql-code-generator init

    Welcome to GraphQL Code Generator!
    Answer few questions and we will setup everything for you.

? What type of application are you building?
どのアプリケーションを使用していますか？
⇒ Application built with React

? Where is your schema?: (path or url)
Schemaファイルはどこにありますか？
⇒ ./schema.graphql

? Where are your operations and fragments?:
オペレーションやフラグメントはどこにありますか？
⇒ src/graphql/*.graphql

? Where to write the output
アウトプットファイル先はどこにしますか？
⇒ src/graphql/generated.tsx

? Do you want to generate an introspection file?
イントロスペクションファイルを生成しますか？
⇒ No

? How to name the config file? codegen.ts
コンフィグファイルの名前はどうしますか？
⇒ codege.ts(default)

? What script in package.json should run the codegen?
スクリプトの名前はどうしますか？
⇒ codegen
```

```graphql:schema.graphql
type Blog {
  title: String!
  author: String!
  body: String!
  createdAt: String!
}

type Query {
  blogs: [Blog!]!
}
```

```graphql:src/graphql/operation.graphql
query GetBlogs {
  blogs {
    ...BlogFields
  }
}

fragment BlogFields on Blog {
  title
  author
  body
  createdAt
}

```

これで生成準備は整いました

### Apollo Client

Apollo Clientを使ってWebからリクエストを送るつもりなので、そのあたりの設定をしていきます。

https://www.apollographql.com/docs/react/

```bash:web/
npm install @apollo/client
npm install --save-dev @graphql-codegen/typescript-react-apollo
```

```typescript:codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
  overwrite: true,
  schema: './schema.graphql',
  documents: 'src/graphql/*.graphql',
  generates: {
    'src/graphql/generated.tsx': {
      plugins: [
        'typescript',
        'typescript-operations',
        'typescript-react-apollo',
      ],
    },
    // mockサーバー側のSchemaファイルを生成
    'mock/schema.graphql': {
      plugins: ['schema-ast'],
    },
  },
}

export default config
```

```bash
npm run codegen
```

きちんとファイルが生成されていたら完了です:ok:

<details><summary>src/graphqll/generated.tsx</summary>

```ts:src/graphqll/generated.tsx
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
const defaultOptions = {} as const;
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: { input: string; output: string; }
  String: { input: string; output: string; }
  Boolean: { input: boolean; output: boolean; }
  Int: { input: number; output: number; }
  Float: { input: number; output: number; }
};

export type Blog = {
  __typename?: 'Blog';
  author: Scalars['String']['output'];
  body: Scalars['String']['output'];
  createdAt: Scalars['String']['output'];
  title: Scalars['String']['output'];
};

export type Query = {
  __typename?: 'Query';
  blogs: Array<Blog>;
};

export type GetBlogsQueryVariables = Exact<{ [key: string]: never; }>;


export type GetBlogsQuery = { __typename?: 'Query', blogs: Array<{ __typename?: 'Blog', title: string, author: string, body: string, createdAt: string }> };

export type BlogFieldsFragment = { __typename?: 'Blog', title: string, author: string, body: string, createdAt: string };

export const BlogFieldsFragmentDoc = gql`
    fragment BlogFields on Blog {
  title
  author
  body
  createdAt
}
    `;
export const GetBlogsDocument = gql`
    query GetBlogs {
  blogs {
    ...BlogFields
  }
}
    ${BlogFieldsFragmentDoc}`;

/**
 * __useGetBlogsQuery__
 *
 * To run a query within a React component, call `useGetBlogsQuery` and pass it any options that fit your needs.
 * When your component renders, `useGetBlogsQuery` returns an object from Apollo Client that contains loading, error, and data properties
 * you can use to render your UI.
 *
 * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
 *
 * @example
 * const { data, loading, error } = useGetBlogsQuery({
 *   variables: {
 *   },
 * });
 */
export function useGetBlogsQuery(baseOptions?: Apollo.QueryHookOptions<GetBlogsQuery, GetBlogsQueryVariables>) {
        const options = {...defaultOptions, ...baseOptions}
        return Apollo.useQuery<GetBlogsQuery, GetBlogsQueryVariables>(GetBlogsDocument, options);
      }
export function useGetBlogsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetBlogsQuery, GetBlogsQueryVariables>) {
          const options = {...defaultOptions, ...baseOptions}
          return Apollo.useLazyQuery<GetBlogsQuery, GetBlogsQueryVariables>(GetBlogsDocument, options);
        }
export function useGetBlogsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions<GetBlogsQuery, GetBlogsQueryVariables>) {
          const options = {...defaultOptions, ...baseOptions}
          return Apollo.useSuspenseQuery<GetBlogsQuery, GetBlogsQueryVariables>(GetBlogsDocument, options);
        }
export type GetBlogsQueryHookResult = ReturnType<typeof useGetBlogsQuery>;
export type GetBlogsLazyQueryHookResult = ReturnType<typeof useGetBlogsLazyQuery>;
export type GetBlogsSuspenseQueryHookResult = ReturnType<typeof useGetBlogsSuspenseQuery>;
export type GetBlogsQueryResult = Apollo.QueryResult<GetBlogsQuery, GetBlogsQueryVariables>;
```
</details>

これでWebの開発が進められるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/cb18e803-597b-a3f4-b616-56efdb1a82ce.png)

次回からは、TOPページの作成に入ります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/c344b98f-8c07-c5b1-bdfc-57480dafeb1a.png)