GraphQL Schemaをファイル分割してドキュメンテーションする
^の続きです。 前回は glob と fs を使ってschema/**/*.gql
ファイルを結合し、graphdoc を使ってドキュメンテーションページを生成する記事を投稿しました。
まったく同じ目的のために merge-graphql-schemas
という npm パッケージがあったので、これを使ってドキュメンテーションのビルドスクリプトを改良しました。
パッケージのインストール
前回の状態から、glob
をアンインストールして、代わりにmerge-graphql-schemas
をインストールします。
$ yarn remove glob
$ yarn add --dev merge-graphql-schemas
schema.js
の変更
前回はschema.js
からエクスポートした文字列配列をスキーマとして graphdoc に読み込ませましたが、 今回はschema.js
を実行することで静的なschema.gql
ファイルを書き出し、これを graphdoc に渡します。
結合されたスキーマが静的ファイルとして存在することで、他の GraphQL 周辺ツール(コード生成など)への連携が容易になります。
schema.js
は次のように書きました。fileLoader
とmergeTypes
がmerge-graphql-schemas
パッケージから提供される関数です。
最終的に結合された文字列がschema.gql
ファイルに書き出されます。
やっていることは前回とだいたい同じですが、この関数でマージされたスキーマは内部でスキーマ単位にソートされていて、ファイル名ではなくtype
やinterface
の名前でソートされているようです。
const path = require("path");
const fs = require("fs");
const { fileLoader, mergeTypes } = require("merge-graphql-schemas");
const typesArray = fileLoader("schema/**/*.{gql,graphql}", {
recursive: true
});
const mergedSchema = mergeTypes(typesArray);
fs.writeFileSync("schema.gql", mergedSchema, { encoding: "utf8" });
こんな感じで、schema
から順番に何らかのルールでソートされています。
schema {
query: Query
mutation: Mutation
}
type Query {
# Return the hero by episode.
hero(episode: Episode): Character
# Return the Human by ID.
human(id: ID!): Human
# Return the Droid by ID.
droid(id: ID!): Droid
}
type Mutation {
# Save the favorite episode.
favorite(episode: Episode!): Episode
}
# A character in the Star Wars Trilogy
interface Character {
id: ID!
name: String
friends: [Character]
appearsIn: [Episode]
secretBackstory: String
}
...
graphdoc でスキーマを読み込む
package.json
のbuild
スクリプトを次のように変更します。事前にschema.js
を実行し、吐き出されたファイルをgraphdoc
に渡します。
"scripts": {
"build": "node schema.js && graphdoc -s schema.gql -o docs -f"
},
これで元どおりドキュメンテーションが生成されます。
schema.gql
を静的に吐き出して Git 管理に含めておくと、このリポジトリを外部から参照することで簡単に GraphQL のスキーマが得られるので、 クライアントサイドとサーバーサイドそれぞれから参照して利用するのに便利です。.gql
ファイルなので実装の言語も問いません。
この方法で作成したスキーマから TypeScript の型定義を生成してクライアントサイドで利用するのを仕事で試しているので、いい感じに知見が溜まったらまた記事を書きます。
だんだん API 仕様中心開発っぽくなってきたぞ!さらばバックエンド実装にブロックされるフロントエンド開発!