Next.jsのApp Router & RSCでApollo Clientを使う
はじめに
これまでRESTのバックエンド&インフラを主に担当していて、Next.jsもGraphQLも詳しくないのですが、GraphQLを学ぶついでに、最近よく聞くApp RouterとRSC(React Server Components)も学べたら一石二鳥じゃん!ということで触ってみたのでその記録を残します。
前提
GraphQLのバックエンドは構築済みとします。
私はGoのgqlgenというライブラリを使って構築しました。
リクエストとレスポンスは以下のような形式になっています(リクエストが左、レスポンスが右)。
今回のフロントのコードも含めて、ソースコードは以下に置いていますのでご参考までに!
また、Next.jsのプロジェクトの作成も完了していることとします。
やったこと
型定義のコード自動生成
必要なパッケージのインストール
GraphQLのスキーマ定義からフロント用のコードを生成するために、GraphQL Code Generatorを使います。
まずは必要なパッケージをインストールします。
npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-graphql-request
@graphql-codegen/typescript-operations @graphql-codegen/typescript-resolvers
設定ファイルの作成
schema: ../backend/graph/schema.graphqls
documents: ./graphql/query/*.graphql
generates:
./graphql/dist/client.ts:
plugins:
- typescript
- typescript-operations
- typescript-graphql-request
スキーマ定義は、バックエンド構築時に構築したものを使いまわしています(schema:
の部分)。
フロントエンドからのクエリを定義するファイルを以下のように記述します(documents:
の部分)。
query getMessages {
messages {
id
user
text
createdAt
}
}
mutation postMessage($user: String!, $text: String!) {
postMessage(user: $user, text: $text) {
id
user
text
createdAt
}
}
コードの自動生成実行
これで準備ができたので、package.jsonにスクリプトを用意して、実行します。
"scripts": {
"gen": "graphql-codegen --config ./graphql/codegen-client.yml"
}
うまくいけば、dist
ディレクトリにclient.ts
というファイルが生成されます。
Next.jsのApp Router & RSCでデータをフェッチする
ここからが本題です、Next.jsのRSCで使用する方法は、zennなどの日本語の記事はまだ少なかったのですが、以下のApolloの公式のブログを見ると、@apollo/experimental-nextjs-app-support
というライブラリを使えばできそうです。
パッケージのインストール
npm i @apollo/client @apollo/experimental-nextjs-app-support
共通で使用する設定ファイルの作成
RSCでApollo Clientを使用するために、共通で使用する設定ファイルを作成します。
import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
export const { getClient } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "http://localhost:8080/query", // 各自の環境で書き換えてください
fetchOptions: { cache: "no-store" }, // 一旦、キャッシュしない設定で逃げる
}),
});
});
page.tsxの編集
データを取得した結果をフロントに表示する部分です。
import { getClient } from "@/lib/apolloClient";
import { GetMessagesQuery, GetMessagesDocument } from "@/graphql/dist/client";
export default async function QueryPage() {
// クエリ
const { data: queryData } = await getClient().query<GetMessagesQuery>({
query: GetMessagesDocument,
});
const messages = [...queryData.messages];
return (
<main>
{messages
.sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1))
.map((message) => (
<div key={message.id}>
<h1>{message.text}</h1>
</div>
))}
</main>
);
}
表示結果
以下のように表示されればOKです!
まとめ
Next.jsもGraphQLもほとんど触ったことのない技術だったので、ざっと動くところまで通してみましたが、キャッシュとかまで考えると奥が深そうなので引き続きキャッチアップしていきたいと思います(一旦今回やキャッシュしない設定で逃げちゃいました)。
Discussion