一覧へ

Apollo Clientの強みと弱みを考える

突然ですが、Apollo Clientの開発を支援するツールである Nau を作り始めて1年以上が経過しました。

この間、さすがにApollo Clientについて多少は詳しくなりました。せっかくなのでこの1年の開発から得られた学びなどを、今後いくつかに分けて話していけたらなと思います。 今回はNauの開発を始めるキッカケになったApollo Clientの強みと弱み、特に生産性や開発者体験に目を向けて話していきましょう。

なお、ここではApollo Clientに加えてReactとTypeScriptの使用を前提として話します。 その他の環境についてはあまり詳しくないので、私の考えが妥当でない可能性があります。ご注意ください。

Apollo Clientの良いところ

Reactで使うGraphQLクライアントと言えば、Apollo Client・Relay・urqlあたりが有名です。 私はもともとRelayを使っていましたが、2020年末頃からお手伝いしているお客様の案件でApollo Clientを使い始めました。

Apollo Clientを始めてまず感じた良さは、開発者に対して手厚い支援があるところでした。ドキュメントやサンプルは豊富にありますし、Apollo Studioなどのクエリの実行環境からVS Codeのエクステンションブラウザのエクステンションまで、一通りあります。 対して、当時のRelayは(現在は改善されていますが)ドキュメントがほぼなくソースコードを見て細かい挙動を解析するような生活を強いられていたので、それと比較すると体験は当然良かったです。

また、Apollo Clientは柔軟で高い拡張性があり、実行時に行われるほぼ全てに干渉できます。それによりサードーパーティー文化が盛り上がっているかはさておき、困った時に自分で簡単な処理を書いてハックできるところは技術選定では安心感がありますね。

最後に、単純に使用している人が多いので、調べたらGitHubのIssue含め答えが出てきやすいところも技術選定観点では安心です。

Apollo Clientの良くないところ

良くないところは、ハッキリ言ってRelayと比較すると大規模なアプリケーションではバグりやすいことですね。悲しいですがそう言わざるをえません。 Apollo Clientのバグが多いという意味ではなく、Apollo Clientで作ったアプリケーションにバグを仕込んでしまう可能性が高いです。

まず、そのまま使うとQueryからTypeScriptの型を生成できませんし、書いたQueryが正しいのか実行前に静的に検証できません。普段TypeScriptを使っているユーザーからするとJavaScript時代に戻ったのかのような感覚になります。 なので、ほとんどのユーザーはGraphQL Code Generatorと一緒に使って、TypeScriptの型やコードを自動生成したりQueryの検証をしたりしています。

ここまではGraphQL Code Generatorがあるので良いでしょう。本当の辛いところはここからです。

キャッシュ関連は酷いです。バグの温床です。「下手に弄るとすぐバグるから、とりあえずキャッシュ使わずにリフェッチして正しい状態にしよう」みたいなのはあるあるなバッドノウハウだと思います。 Apollo ClientはRelayと異なりバックエンドのスキーマがどうなっているか事前に定めないので、フレームワーク側でキャッシュ関連の自動化が困難です。 できることと言えば、様々なケースに対応した柔軟性の高いキャッシュの仕組みを提供するということになりますが、その柔軟性、もとい複雑性が人類が使いこなすにはまだ早すぎるように感じます。

また、Relayでは常識となっているコロケーションが困難なのも大規模なアプリケーションでは辛いところです。 ここで言うコロケーションというのは、フラグメントとコンポーネントを同じところに配置し、コンポーネントとコンポーネントで必要なデータの定義をセット運用することです。こうすることで、コンポーネントに必要なデータがコンポーネントの外部に依存しないのでリファクタリングが容易になります。 しかしながらApollo Clientでコロケーションしようとすると、フラグメント内に閉じる変数を作れなかったり、フラグメント単位でリフェッチできなかったりするので、なかなか上手くいきません。

総じて、アプリケーションが大きくなるにつれてRelayは(慣れもあり)開発者体験が良くなっていくのに対して、Apollo Clientでは全く逆のことが起きると感じます。始めるのは簡単ですが大きくするのが難しいです。

対応策

そんなこんなでApollo Clientの開発者体験は若干厳しいのですが、当然ながら様々な努力が過去に、または現在進行形で存在しています。

日本語で参照できる情報としては、QuramyさんがApollo Clientでコロケーションが行える仕組み作りにチャレンジされています。 https://qiita.com/Quramy/items/b4d42f5b1c52d5cc171d https://github.com/Quramy/apollo-link-fragment-argument

GraphQL Code Generatorでコロケーションを行えるようにするプラグインも存在しています。これは内部的にRelayのコンパイラを使用しています。 https://www.the-guild.dev/blog/graphql-codegen-relay-compiler https://www.graphql-code-generator.com/plugins/relay-operation-optimizer

異色なところでは、用途は違うのですがApollo Client上にRelayのAPIを完全に作ってしまうものなんかもあります。当然コロケーション等ができます。こちらも内部的にはRelayのコンパイラを使っていたと思います。 https://github.com/microsoft/graphitation

そして私は Nau というツールを作っています。 https://github.com/kazekyo/nau Relayへの依存なしで、コロケーションをサポートしたり、ディレクティブ等でキャッシュの処理を宣言的かつ簡易に書くことができるようなツールです。

Apollo Clientの弱みと向き合う

Apollo Clientの根本的な弱みは「静的解析が苦手」「前提条件が少なく自動化できる領域が狭い」「一緒に使用するツールを限定できないため連携を極められない」みたいなところにあります。 これらの弱みはApollo Clientが簡単さや間口の広さを重視しているからと言えるので、今後劇的に改善されるような未来はあまり見えません。 Apollo Clientはその代わりに拡張性を高めているので、なんとかGraphQL Code Generatorのようなサードパーティーのツールでうまく補完しながら付き合っていきたいですね。 みなさんも、業務で作った仕組みがあれば是非OSS化していただけると良いと思います。人類が幸せになれる余地はまだたくさんあるのではないでしょうか。

ちなみに、私が作っているツールの目標はこれらの弱みを踏まえて、「Relayのサーバー仕様に準拠しているバックエンドがある」環境に限定して「Apollo Clientのやり方に沿った形で開発者の体験を向上させる」としています。 Apollo Clientユーザー全員は救えませんが、利用環境をある程度限定した状態で、その中で体験を良くするということですね。

またNauの紹介は後日書きたいと思いますので、今日はこの辺りで。