これはなに?
個人的な興味で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を作成しました。
# ------------------------------------------------------
# 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
の内容は以下になります
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
で生成されたコードはこちらになります。
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
}
}
`
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
余談
今までNoSQLを使うことが多かったのでGraphQLを触ってこなかったのですが、RDB系を使う時にこれはもう外せないなというイメージでした。
引き続き学んでは記事を書いてを繰り返していこうと思います。
ではまた!
参考記事