^の続きです。
前回は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仕様中心開発っぽくなってきたぞ!さらばバックエンド実装にブロックされるフロントエンド開発!