error codes

ソフトウェアエンジニアリングなど、学んだこと、思ったことの記録です。

なんで GraphQL クエリ書いているんだっけ?

雑記。

graphql-codegen

GraphQL は便利だ。

うまく言えない部分も多いけど、 GraphQL を使ったプロジェクトと、普通の HTTP の API を使ったプロジェクトだと、GraphQL を使ったプロジェクトの方が開発体験が良い。あるいは、開発体験を上げるためのステップが少なく感じる。 GraphQL 周辺のエコシステムが充実しているのもあるだろう。

その中でよく使われるのは graphql-codegen だ。自分の周りだと、ほとんどの場合、 graphql-codegen を使ってフロントエンドのコード生成をしている。

一方で、少しイマイチだな、と思う場面が増えてきて、それでこれを書いている。

SQL と O/R Mapper

GraphQL はクエリ言語だが、昔からあるクエリ言語が SQL だ。

そのままの SQL を使うことも多いけど、アプリケーションからは何らかの O/R Mapper やクエリビルダーと呼ぶようなものを使うことが自分は多い。 O/R Mapper の功罪はあると思うけど(自分は深くはわからない)、長くアプリケーション開発で SQLRDBMS が使われるに至った貢献の一つをしているような気もする。

クエリをプログラマブルに扱えるし、特に現代であれば、言語の強力な型システムの恩恵を受けることができる。

Prisma を初めて触ったときは結構感動した(と同時に TypeScript の型システムの柔軟さにも感動した)。

クエリにも、その結果にも、厳密な型が効く。

そうであれば、同じクエリ言語である GraphQL を扱う場面でも同じような体験が得たいように思う。

GraphQL を TypeScript で書く

graphql-codegen で GraphQL クエリを書くときは、下記のような感じでテンプレートリテラルでクエリを書いたり、クエリを別ファイルにして書いたりしている。

const GetArticleQuery = gql`
  query getArticle($id: Int!) {
    article(id: $id) {
      id
      title
      body
    }
  }
`

VS Code でもエクステンションを入れて、スキーマがちゃんと読まれていれば、ちゃんと補完も効いている気がするけど、そんなに体験は良くはない(あと、正直、自分は GraphQL のシンタックスをあんまり覚えていなかったりする)。

クエリの表現(仕様?)上の問題も少し感じていて、 Fragment と variables の噛み合わせもあまり良くなかったりする。(もっともこれをクエリ言語に求めるのも求めすぎのような気もしていて、それこそ別の言語やツールでプリプロセスするべき範囲なのかもしれない)

あと、コード生成のタイミングの問題もある。クエリを書いてから、型を含むコード生成をするわけだけど、新しいクエリを書いたりちょっとクエリを修正したりするたびに、コード生成のコマンドを実行するのは面倒だと感じる。

一方、 Prisma の体験を振り返ってみると、スキーマを変えた後に一度だけコード生成をすれば良いだけだし、 TypeScript のコード上でガンガン補完が効く。

フロントエンドでの GraphQL を使った開発も、同じように TypeScript の世界にいたままクエリをかけるのがいいのではないかと思うようになった。

そんな感じの体験を実現するライブラリ

TypeScript のコード上で、型の恩恵を受けつつ GraphQL のクエリを組み立ててくれるライブラリは、いくつかある。

例えば、 genql のリンク先の補完の様子とかを見てほしいけど、こういう体験ができたらいいよねと思う。

ちなみに最後の GQty はかなり野心的な気がしていて、自分は、 RailsActiveRecord をフロントの世界に持ってきてしまったものように見えた。

ここまで書いてきて、結局、自分はちゃんとしたプロダクト開発で、これらのライブラリを使ったことはないので、実際の開発体験はどうなのかみたいのは自信がない。

その他

こんな感じのことをここ最近考えていて、自分でも GraphQL のクエリビルダを書いてみていた。

GitHub - daisaru11/graqq: Write GraphQL queries in TypeScript

一方で、既存のライブラリの劣化再生産みたいにしかならなくて、ちょっと書き続けるモチベが落ちている。

ちょっと面白かったのは、TypeScript の型生成の周辺で、 TypeScript の Compiler API を触ったところ。TypeScript の AST を組み上げて、バッとコードを生成する。 下記の記事がわかりやすい。 zenn.dev

他の場面でも、いろいろ便利に使えそうなものに感じたので、機会があれば使ってみたい。