Next.js 13にApollo Serverを建ててみた
はじめに
業務でGraphQLをApollo ServerとClientを使う機会があって、結構GraphQLを気に入りました。
が、最初の構築や細々した設定を先輩エンジニアがしてくれたため、そこら辺を全く理解せずに実装していた。そして、パフォーマンス改善やキャッシュ、認証についてもあまり理解ができてないので、個人開発でじっくり調べながら実装していこうと思いました。
今回の記事は、そんな中でNext.js 13にApollo Serverを建てた過程をまとめていきます。
使用ライブラリ
- @apollo/server: 4.7.4
- @as-integrations/next: 2.0.0
- graphql: 16.6.0
- graphql-tag: 2.12.6
- @graphql-codegen/cli: 4.0.1
- @graphql-codegen/schema-ast: 4.0.0
- @graphql-codegen/typescript: 4.0.1
- @graphql-codegen/typescript-resolvers: 4.0.1
やったこと
- GraphQL Code Generatorのセットアップ
- GraphQL schemaの記述 + 分割したschemaをマージ
- resolverの型生成 + resolverの記述
- *.graphqlをimport + Apollo Serverの初期化
- Next.js 13のRoute HandlersにApollo Serverを設定
GraphQL Code Generatorのセットアップ
自分がTypeScriptを使用している関係でGraphQLの型付けが必須だったので、GraphQL Code Generatorを使用して、型生成を行なっていきます。
必要なパッケージのインストール
yarn add graphql
yarn add -D @graphql-codegen/cli
設定ファイルの初期化
yarn graphql-codegen init
設定ファイル
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: './src/libs/gql/schema/**/*.graphql',
documents: ['src/**/*.tsx', 'src/**/*.ts'],
ignoreNoDocuments: true,
generates: { ... },
};
export default config;
GraphQL schemaの記述 + 分割したschemaをマージ
# tsファイルにはリゾルバーを記述しています
src/libs/gql/schema
├ user
| ├ mutation
| | └ createUser.ts
| ├ query
| | └ user.ts
| └ schema.graphql
├ Mutation.ts
└ Query.ts
今回、ドメインごとにschemaを記述したかったため、このような構成にしました。
この構成の場合、Apollo ServerにtypeDefsを渡すためschemaを1つにまとめる必要がありました。
ので、@graphql-codegen/schema-astを使用
const config: CodegenConfig = {
...
generates: {
'./src/libs/gql/generated/schema.graphql': {
plugins: ['schema-ast'],
},
},
};
これがめっちゃ便利で試した感じ、同じ型があると勝手にマージしてくれる模様。
なので、各スキーマ内で別々のQueryやMutationを書いてもモーマンタイ!!
# /user/schema.graphql
type Query {
users: [User!]!
}
# /book/schema.graphql
type Query {
books: [Book!]!
}
# /generated/schema.graphql(出力)
type Query {
users: [User!]!
books: [Book!]!
}
resolverの型生成 + resolverの記述
resolverの型を生成するために@graphql-codegen/typescript-resolversを使用。
const config: CodegenConfig = {
...
generates: {
'./src/libs/gql/generated/resolvers-types.ts': {
config: {
useIndexSignature: true,
},
plugins: ['typescript', 'typescript-resolvers'],
},
},
};
resolverを記述するとき、resolvers-types
から生成した型をimport
import { QueryResolvers } from '@/libs/gql/generated/resolvers-types';
export const userQuery: QueryResolvers['user'] = () => ({
id: '0',
name: 'john',
age: 5,
});
*.graphqlをimport + Apollo Serverの初期化
@graphql-codegen/schema-astを使って1つにまとめたschemaをApollo Server初期化時にtypeDefsとして渡す必要があったので、webpackで*.graphql
ファイルをimportできるように設定する。
loaderはgraphql-tag/loaderを使用。
TypeScriptを使用しているため、型定義も作成。
const nextConfig = {
webpack: (config) => {
config.module.rules.push({
test: /\.(graphql|gql)/,
exclude: /node_modules/,
loader: 'graphql-tag/loader',
});
return config;
},
};
declare module '*.graphql' {
export default DocumentNode;
}
これで*.graphql
をimportできるようになったので、Apollo Serverを初期化する
import typeDefs from '../generated/schema.graphql';
import { resolvers } from './resolvers';
import { ApolloServer } from '@apollo/server';
const server = new ApolloServer<{}>({
resolvers,
typeDefs,
});
Next.js 13のRoute HandlersにApollo Serverを設定
Next.jsにApollo Serverを統合するのに便利な@as-integrations/nextが用意されている。
app directoryにも対応済みなので、今回はこれを使用。
import { ApolloServer } from '@apollo/server';
import { startServerAndCreateNextHandler } from '@as-integrations/next';
import { NextRequest } from 'next/server';
const server = new ApolloServer<{}>({
resolvers,
typeDefs,
});
const apolloServer = startServerAndCreateNextHandler<NextRequest>(server, {
context: async (req) => ({ req }),
});
export { apolloServer as GET, apolloServer as POST };
今後やりたいこと
- Prisma x Vercel Postgresでデータベースを構築、Apollo Serverからデータを取得できるようにする
- Apollo Serverへのアクセス認証・認可
Discussion