Apollo Server + Nexus + PrismaでGraphQL開発: フレームワーク紹介編
この記事は、いかずちさんだー Advent Calendar 1日目の記事です。
趣旨
最近、弊社サービス(toridori marketing)の管理画面を新調しようという気運が高まったので、サーバサイドとしては新しめの技術であるGraphQLを採用してみることになりました。
まだまだ開発中の状態ですが、ほとんど日本語の情報が存在しない中で開発を進めてきたので、これまでを振り返る形で得られた知見を言語化していきたいと思っています。
展望が見えていない状態で執筆を始めているのでなんともいえないところではありますが、数記事にまたがる連載になるかと思います。
たぶん全体が支離滅裂になるのでアドベント連載終わったら整理してBooksにしたいな~。
GraphQLとは
GraphQLの概要や善し悪しについては、先行する記事がたくさんあるのでさらっと流すことにします。
ひとことで言えば、「gRPCとかの効率がいい方法で他のコンテナ(や外部のRESTなど情報ソース全般)から情報を取ってきて、統一された形式で出力する」のが楽です。
よく言われること:
- フロントエンドから直接アクセスする唯一の存在であるBFFを実現できる
- Apollo Clientが極めて優秀であり、フロントの実装が楽
- 「欲しいものだけもらう」ことが簡単
- 芋づる式に様々なデータを取得できる
- 型がある
- 宣言的UIの実装をしやすい
- etc...
参考にすべき先行資料
基本的にはvvakame氏の資料を教科書にしつつ、困ったことがあったらGitHub GraphQLの実装に従えば良いでしょう。
以下の解説では、vvakame氏の資料との内容の重複を気にせず書いていきます。
コードファーストかスキーマファーストか
GraphQLを実装する上で、最初に当たる壁がこれです。
schema.graphql
をどのように作るかが問われています。
現代的にはほぼコードファーストで書くことになると思います。
コードファーストとは
コードを先に書いて、コードからスキーマを生成します。
開発言語がGoやRust, TypeScriptなどの現代的な言語の型機能を用いることができるのは最大のメリットです。
ただし、「スキーマはバックエンドが自動生成するもの」になってしまうので、バックエンドとフロントエンドの連携が必要です。
スキーマファーストとは
スキーマを先に書いて、スキーマからコードを生成します。
正直、GraphQLのIDLの表現力があまりよろしくないので微妙です。
今回使ったフレームワーク・ライブラリ
今回は、開発言語としてTypeScriptを採用しました。
そんなに強い理由はない[1]ですが、フロントとバックエンドの開発言語を揃えることで、人員のやりくりとか言語知識の教授とかがうまくいくようになることを期待しています。
Apollo Server
TypeScriptでは一般的なGraphQLサーバフレームワークです。
GraphQLに関する様々な機能があるのですが、ほとんど使っていません…。
後述するNexusを利用するために使っているという感じです。
ただ、Expressに乗っかることができるので、認証やヘルスチェックだけをRESTにするのが簡単なのはGoodです。
Nexus
Apollo Serverに対応する型安全なGraphQLスキーマビルダーです。
これを使って、コードファーストな開発を実現します。
複数ファイルに分割してスキーマ定義を書いたり、ページングのひな形を作ってくれたり、なかなか良い奴です。
Prisma
TypeScript用のORMです。
昔はPrisma自体もGraphQL用に作られていましたが、現在では発展して一般向けORMとなっています。
DBのテーブル定義をPrisma Schemaとして持っていて、それをDBからpullしたりpush(つまりMigrate)したりすることができます。
うまく開発すればN+1も相当回避してくれるので優秀です。
nexus-prisma
絶賛early preview中の、PrismaとNexusを組み合わせるためのライブラリです。
さすがに一般的に使用することは勧められませんが、これを使うことでPrisma Schema(=DBの型情報)をGraphQLまで一貫して届けることができます。
以前に似たような機能があるNexus Plugin Prismaというものがあったのですが、保守ができなくなったらしく書き直されているのがこれです。
将来的には簡単なCRUD操作やページングまで自動生成してくれるようになるらしいので期待しましょう。
その他開発環境など
VSCode Dev Container
開発者同士の環境の差異をなくすために、DevContainer上で実装しています。
Win/Mac/LinuxなどのOSを含めた環境差を完全に吸収できるのは魅力です。
DockerFileは今のところ完全にVSCode自動生成のデフォルトですが、全然問題なく使えています。
devcontainer.jsonに必要なVSCodeエクステンション[2]の設定などを加えておきましょう。
GitHub Copilot
現在TechnicalPreview中の、GitHubの開発する補完機能です。
複数行の補完も平気でしてくれるし、補完の内容もなかなかいいです。
コメントが思った通りに補完されたときはびびりました。エスパーかよ。
prismaのコードは古い物を学習しているらしく、findUnique
メソッドがfindOne
になってしまうので粛々と直しましょう。
終わりに
今回は全然内容がある文章を書けませんでしたが、明日からはもっと具体的な開発方法について述べていきたいと思います。
引き続きよろしくお願いします。
Discussion