LoginSignup
14
8

More than 1 year has passed since last update.

Next.js x URQLでGraphQL Code Generatorを使う

Last updated at Posted at 2022-03-18

これはなに?

個人的な興味でGraphQLに入門したのでその導入手順を書き残しておこうと思います。

この記事が新たにGraphQLやURQLに入門する方の手助けになれば幸いです。

この記事のゴール

以下の理解を得ることをゴールとします

  • URQLを用いてGraphQLコードの自動生成が行えるようになること

この記事に書かれていないこと

  • NestJSのGraphQL Server設定方法
  • NestJS側のSchema作成方法
  • モノレポ環境の設定方法

導入

早速ですが、導入していきます。

上の実際のコードを参照していただければわかりますが、以下の環境で実装していきます。

箇所 選定
フロントエンド Next.js
サーバーサイド NestJS
コード自動生成ツール GraphQL Code Gen
GraphQL Client URQL

1. 必要なパッケージのインストール

まずはコード自動生成ツールのGraphQL Code GeneratorのCLI(以下、codegen)を導入していきます。

CLIのインストール

$ npm install @graphql-codegen/cli

↓参考

URQL用のコード生成パッケージのインストール

$ npm install @graphql-codegen/typescript
$ npm install @graphql-codegen/typescript-operations
$ npm install @graphql-codegen/typescript-urql

2022.3.20追記
公式では@graphql-codegen/typed-document-nodeもインストールするように書かれていますが、
コード生成した際に@graphql-codegen/typescript-urqlでの生成とバッティングするためインストールをしていません。

※この問題に関しては以下のissueでも上がっていました。
https://github.com/dotansimha/graphql-code-generator/issues/7578

指摘ありがとうございます! @masashi-sutou

↓参考

2. codegenの初期化と自動生成の実行

初期化の実行

$ npx graphql-codegen init

$ npm run install # 選択したプラグインをインストール

graphql-codegen initで入力した内容は以下になります。

➜  web git:(main) ✗ npx graphql-codegen 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) ../api/src/schema.gql
? Where are your operations and fragments?: src/**/*.graphql
? Pick plugins: TypeScript (required by other typescript plugins), TypeScript Operations (operations and fragments), TypeScript React Apollo (typed components and HOCs)
? Where to write the output: src/generated/graphql.tsx
? Do you want to generate an introspection file? Yes
? How to name the config file? codegen.yaml
? What script in package.json should run the codegen? generate

コードの自動生成です

正常に生成されると以下のような表示になります。

$ npm run generate                                  

> project-name@0.1.0 generate
> graphql-codegen

  ✔ Parse configuration
  ✔ Generate outputs

3. 動作確認用のページの作成

自動生成されたコードで動作確認をしてみます。

今回は以下のようなAPIを作成しました。

schema.gql
# ------------------------------------------------------
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
# ------------------------------------------------------

"""
A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.
"""

type HealthCheck {
  message: String!
}

type Query {
  healthCheck: HealthCheck!
}

HealthCheckを呼び出したらレスポンスでhealthyという文字列を返すシンプルな形です。

codegenの初期化時に自動作成されたcodegen.yamlの内容は以下になります

codegen.yaml
overwrite: true
schema: "../api/src/schema.gql"
documents: "src/graphql/**/*.graphql"
generates:
  src/generated/graphql.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-urql"
  ./graphql.schema.json:
    plugins:
      - "introspection"

npm run generateで生成されたコードはこちらになります。

src/generated/graphql.tsx
import gql from 'graphql-tag'
import * as Urql from 'urql'
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 Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  String: string
}

export type HealthCheck = {
  __typename?: 'HealthCheck'
  message: Scalars['String']
}

export type Query = {
  __typename?: 'Query'
  healthCheck: HealthCheck
}

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

export type HealthCheckQuery = {
  __typename?: 'Query'
  healthCheck: { __typename?: 'HealthCheck'; message: string }
}

export const HealthCheckDocument = gql`
  query HealthCheck {
    healthCheck {
      message
    }
  }
`
src/pages/healthCheck.tsx
const HealthCheck: NextPage = () => {
  // HealthCheck APiの呼び出し
  const [result] = useHealthCheckQuery()

  if (!result.data) {
    return <Text>Error Occurred</Text>
  }

  const message = result.data.healthCheck.message

  return <Text>{message}</Text>
}

export default HealthCheck

表示確認
スクリーンショット 2022-03-19 5.27.23.png

余談

今までNoSQLを使うことが多かったのでGraphQLを触ってこなかったのですが、RDB系を使う時にこれはもう外せないなというイメージでした。

引き続き学んでは記事を書いてを繰り返していこうと思います。

ではまた!

参考記事

14
8
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
14
8