graphql-codegen を Next.js の CSR と SSR/SG で使う際の知見
動機
graphql-codgen
という、GraphQL
のスキーマから型とかSDK
を自動生成してくれるライブラリがとても便利なので個人開発で愛用しています。ただ案外、Next.js
のSSR/SG
で利用する記事があまり見当たらなかったので記事にしてみることにしました。
graphql-codegen
について
graphql-codgen
は、冒頭でも述べた通り、GraphQL
のスキーマ(ex. schema.graphql
)から型とかSDK
を自動生成してくれるライブラリです。GraphQL
を使う以上は入れない理由が特にないかな、というくらい便利な代物なので是非導入してください。導入・使用の手順は概ね以下の通りです。
-
graphql-codegen
と周辺プラグインのインストール(yarn
/npm
) -
$ yarn graphql-codegen init
で初期設定(任意) - 設定ファイルの編集(ex.
codegen.yml
) - フロント側での
Query
やMutation
の記述 - コマンドで型や
SDK
の自動生成
また、CSR
、SSR/SG
共通で必要なライブラリやプラグインは以下です。(typescript
は使っている前提)
- graphql
- @graphql-codegen/cli
- @graphql-codegen/typescript
- @graphql-codegen/typescript-operations
- @graphql-codegen/near-operation-file-preset
CSR
CSR
(クライアントサイドレンダリング)でのgraphql-codegen
に関しては、他にも記事がいくつか出ていますが一応書きます。Next.js
とはいえ実質CSR
はReact
なので、React
用のプラグインを導入します。
apollo
はGraphQL
関連のライブラリ等を提供してくれているプラットフォームです。ここでは、データフェッチのための、@apollo/client
をインストールします。
以下のように、App.tsx
をラップして、クライアントを設定することで共通化します。
const client = new ApolloClient({
uri: 'YOUR_GRAPHQL_SERVER',
cache: new InMemoryCache()
});
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
</>
)
}
export default MyApp
では、次にcodegen.yml
を記述して、自動生成の準備をしましょう。CSR
の段階での、codegen.yml
は以下のようになりました。
overwrite: true
schema: "YOUR_GRAPHQL_SCHEMA"
documents: "src/graphql/**/*.graphql"
generates:
src/graphql/types.ts:
plugins:
- "typescript"
src/graphql/:
preset: near-operation-file
presetConfig:
extension: .generated.tsx
baseTypesPath: types.ts
plugins:
- "typescript-operations"
- "typescript-react-apollo"
near-operation-file
を導入している理由については以下の記事を参照。(パフォーマンスの問題です。)
では、取得したいデータのQuery
やMutation
を書いたファイルを作りましょう。サンプルは長くなってしまったので以下アコーディオンに。
GraphQL例
https://github.com/lucasbento/graphql-pokemon を使ってみました。
query getPikachu {
pokemon(name: "Pikachu") {
id
number
name
attacks {
special {
name
type
damage
}
}
evolutions {
id
number
name
weight {
minimum
maximum
}
attacks {
fast {
name
type
damage
}
}
}
}
}
ここまでできたら、以下のコマンドを叩けば、自動生成ファイルが作成されるはずです。
$ yarn codegen
あとは、各ページやコンポーネントで使用しましょう!
使用例
const Pikachu: NextPage = () => {
const { loading, error, data } = useGetPikachuQuery();
if (loading) {
return <></>
}
if (!data?.pokemon) {
return <></>
}
return (
<>
<h1>{ data.pokemon.name }</h1>
</>
)
}
export default Pikachu
SSR/SG
では、本題のSSR
(サーバーサイドレンダリング)やSG
(スタティックジェネレーション)での使用方法です。個人的にはSG
を圧倒的に推しているので、そちらでの使用方法を例にします。(ただし、基本的には同じです。)
SSR/SG
では、graphql-request
というシンプルなクライアントを利用することを想定して、以下のプラグインとプリセットを導入します。
codegen.yml
に以下の記述を追加します。
overwrite: true
schema: "YOUR_GRAPHQL_SCHEMA"
documents: "src/graphql/**/*.graphql"
generates:
src/graphql/types.ts:
plugins:
- "typescript"
src/graphql/:
(...)
+ src/graphql/ssr.generated.ts:
+ preset: import-types
+ presetConfig:
+ typesPath: "./types"
+ plugins:
+ - "typescript-operations"
+ - "typescript-graphql-request"
あとは、$ yarn codegen
で自動生成して使用することができます。
使用例
const Pikachu: NextPage<GetPikachuQuery> = (props) => {
if (!props?.pokemon) {
return <><h1>Pikachu Not Found</h1></>
}
return (
<>
<h1>{ props.pokemon.name }</h1>
</>
)
}
export async function getStaticProps() {
const client = new GraphQLClient('YOUR_GRAPHQL_SERVER')
const sdk = getSdk(client)
const { pokemon } = await sdk.getPikachu()
return {
props: {
pokemon: pokemon,
},
}
}
export default Pikachu
まとめ
graphql-codegen
を使って良いGraphQL
ライフを!
参考
GraphQL
を使って、個人開発を始めたきっかけになった記事です。とても参考になります。
Next.js
で@graphql-codegen/typescript-react-apollo
を使う際にはパフォーマンスの問題にも気を使う必要があるようです。
SSR
でApollo
を使う場合に起きるオーバーヘッドについてです。SG
では、さほど問題とならないかもしれませんが、今回は念の為別のクライアントを使いました。
GraphQL
サーバーです。勉強や実験に使えます。
Discussion