目次
前書き
経緯
GraphQLを使ってアプリケーション開発を試していたところ、
GraphQLサーバとスキーマ定義が一体化していると開発しづらいと感じたため、
分離する方法を調査して試してみました
対象読者
- GraphQLサーバとスキーマ定義を分離したい人
- Node.jsを使用してGraphQLサーバを構築したい人
- graphql-toolsを使用している/使用を検討している人
- GitHubを使用してリポジトリを管理している人
今回使用するものの説明
簡単にですが、今回使用する技術要素について以下に記載します
GraphQLとは
GraphQLとはデータソースと通信するためのクエリ言語であり、以下のような形式で記述します
# 型定義
type Exmaple {
id: ID!
requiredString: String!
string: String
}
# 参照
type Query {
read(id: ID!, string: String): Exmaple
}
# 作成/更新/削除
type Mutation {
create(id: ID!, string: String): Exmaple
update(id: ID!, string: String): Exmaple
delete(id: ID!): Exmaple
}
スカラー型を組み合わせて独自の型を作成したり、
Queryにデータ参照機能のインタフェース定義、
Mutationにデータ編集機能のインタフェース定義を作成することができます
またGraphQLのスキーマ定義そのものがインターフェース定義書となるため、ドキュメント作成の手間を省くことができます
GraphQLサーバとはGraphQLでやり取りできるサーバアプリケーションを指します
graphql-toolsとは
graphql-toolsとはNode.jsのパッケージとして作成されたGraphQLのユーティリティーツール群です
今回、分離したスキーマ定義を読み込むために使用します
本題
GraphQLサーバとスキーマ定義を分離する
スキーマ定義用のGitHubリポジトリを作成する
まず分離したスキーマ定義を管理するためにGitHubにリポジトリを作成します
リポジトリを作成する際は、機能単位でスキーマ定義自体も分離させ、別々のリポジトリで管理します
GraphQLのスキーマ定義は参照機能をQuery型、編集機能をMutation型に定義しなければならないため、通常1ファイルにまとめて定義する必要があります
しかし、graphql-toolsを使用することで、別々のスキーマ定義をマージして使用することができます
こうすることで以下のメリットがあります
- スキーマ定義が機能単位で分割されるため拡張/修正しやすくなる
- 新規追加時/修正時に他の定義への影響をなくすことができる
- スキーマ定義を利用する側のアプリケーションが使用する定義を選択できる
- マイクロサービスアーキテクチャでアプリケーションを構築することも可能になる
GraphQLサーバでGitHubからスキーマ定義を読み込む
スキーマ定義を管理するリポジトリを作成できたら、GraphQLサーバ側にスキーマ定義を取得するための処理を追加します
graphql-toolsを使用したいので、GraphQLサーバはNode.jsで作成します
本記事作成時のNode.jsのバージョンは以下になります
node -v
v16.17.1
npm -v
8.15.0
まずは必要なライブラリをインストールしましょう
GitHubからスキーマ定義を取得したいので、github-loaderとloadライブラリを使用します
npm i @graphql-tools/github-loader @graphql-tools/load
インストールしたgithub-loaderとloadライブラリを使用してスキーマ定義ファイルを取得し、読み込みます
尚、セキュリティ情報となる箇所は環境変数から取得するように記載しています
import { GithubLoader } from '@graphql-tools/github-loader';
import { loadSchema } from '@graphql-tools/load';
const GIT_TOKEN = process.env.GIT_TOKEN;
const USER_NAME = process.env.USER_NAME;
const typeDefs = await loadSchema(
[
`github:${USER_NAME}/feature-a-schema#v1:schema.graphql`,
`github:${USER_NAME}/feature-b-schema#v1:schema.graphql`,
`github:${USER_NAME}/feature-c-schema#v1:schema.graphql`
],
{
loaders: [new GithubLoader()],
token: GIT_TOKEN
}
);
スキーマを読み込むのはloadライブラリのloadSchemaメソッドで、loaderの指定が必要なため、github-loaderを指定します
github-loaderでのスキーマポインター(スキーマ定義が配置されている場所)の記述方法は以下の通りです
`github:${リポジトリのオーナー名}/${リポジトリ名}#${ブランチ名 or タグ}:${スキーマ定義ファイル名}`
このようにGitHubのリポジトリとスキーマ定義ファイルを指定することで外部で管理しているスキーマ定義を読み込むことができます
また、タグも指定できるのでスキーマ定義が更新されたとしてもタグを変更しなければアプリケーション側には影響が出なくなります
読み込むスキーマ定義は1度に複数記載することが可能です
読み込まれた定義は自動的にマージされて1つのスキーマ定義として使用できます
読み込んだスキーマ定義をApollo Serverに渡してGraphQLサーバを起動させることもできます
これによって、スキーマ定義の開発とGraphQLサーバの開発を分離することができました
まとめ
- github-toolsを使用することでGraphQLサーバとスキーマ定義を分離できる
- 分離することでスキーマ定義を変更しやすくなる
- スキーマ定義自体も分割管理できるようになる
- github-loaderを使用することでGitHubから直接スキーマ定義を読み込むことができる
まだ個人開発でしか試せていないですが、チーム開発でメリットを発揮しそうなので機会があれば取り入れてみたいと思います