GraphQL Schemaをファイル分割してドキュメンテーションする
GraphQLのSchemaから静的なドキュメンテーションページを生成するツールとして、graphdocというものがあります。
GraphQL Schemaを渡すと、こんな感じのHTMLを生成してくれます。 これはGraphQL公式のサンプルにもあるStar Wars APIの例。
https://2fd.github.io/graphdoc/star-wars/

このドキュメンテーションを 複数の*.gqlファイルからなるSchemaから生成するために少し小細工が必要だったので紹介します。
GraphQL Schema Language
今回はGraphQL Schema Languageを.gqlという拡張子のファイル(便宜的に以降 gqlファイル と呼びます)で管理します。
TypeScriptやJavaScriptファイル中でテンプレートリテラルとして管理するよりも余計なコードがなくて見やすく、エディタによっては入力支援も得られます。
gqlファイルの欠点は、GraphQL Schema Languageに外部ファイルの参照の仕様がないことです。
JSON Schemaでいう$refに相当するものが定義されていないので、エントリポイントとなるSchemaから分割された型定義などを参照できません。
graphdocでgqlファイルをドキュメンテーションする
graphdocはいくつかの方法でSchemaを読み込めます。 代表的なものはエンドポイントURLを渡してHTTP経由でドキュメンテーションを生成する機能ですが、 gqlファイルを渡すこともできます。 しかしgqlファイルを渡す場合は先述の理由により単一ファイルにすべてのSchemaが記述されている必要があるので、 大きなAPI仕様になると管理が大変です。
複数のgqlファイルからなるSchemaをgraphdocで読み込むためには、JavaScript読み込み機能を使います。
graphdocのschemaFileとして.jsファイルを渡すと、CommonJSとして読み込まれ、exports.defaultの値をSchemaとして使用します。
そしてこのとき、エクスポートするのはSchemaの配列なので、複数のgqlファイルを読み込んで文字列として渡してあげれば目的を達成できます。
手順
npmパッケージを揃える
必要なのは@2fd/graphdocとglobの2つです
> yarn add --dev @2fd/graphdoc glob
schema.jsファイルを記述する
複数のgqlファイルを読み込んで文字列として渡してあげるためのJavaScriptファイルを用意します。
globとfsを使ってファイルを読み込むだけですが、同期的にエクスポートする必要があるのに注意します。
const glob = require('glob');
const fs = require('fs');
const path = require('path');
function loadSchemas() {
  const files = glob.sync('schema/**/*.{gql,graphql}');
  return files.map(file =>
    fs.readFileSync(path.resolve(file), { encoding: 'utf8' })
  );
}
const schemas = loadSchemas();
exports.default = schemas;
npm scriptを追加する
graphdocコマンドを実行するnpmスクリプトを追加します
  "scripts": {
    "build": "graphdoc -s schema.js -o docs -f"
  },
schemaディレクトリにgqlファイルを配置する
あとはひたすらSchemaを書いていくだけです。
実際にStaw Wars APIのSchemaを分割してgraphdocにしたリポジトリを用意したので、詳細はそちらを参照してください。
docsディレクトリに出力しているので、GitHub Pagesで簡単にAPIドキュメントをホストできます。
https://lacolaco.github.io/graphdoc-example/
課題
- gqlファイルに外部参照の仕組みがないので、分割すると参照が途切れる(リネームとかできない)
サーバーサイドの実装に依存しないAPI仕様Centricな開発をしたいのだけど、 Open API Specificationみたいな感じでGraphQL Schemaを使う文化はあまり育っていないようで、苦労しそうな感じがあります。
結局のところひとつのgqlファイルにドカドカ型定義書いていくほうが楽なのかもしれないけど、しばらく分割管理を試してみてから考えましょう。