以前にApollo ClientとRelayの比較記事を書きました。 当時はApollo Clientを使い込んでいませんでしたが、1年以上Apollo Clientを使ってきたので適切な比較ができる頃合いだと思います。
今回はApollo ClientとRelayとの比較ではありますが、Apollo Clientにいろいろなツールを足しつつ比較してみたいと思います。 Apollo Clientはそのまま使うことはおそらく稀なので、こうした比較をすることでより良い比較ができる + 自作のOSSのNauをちょっと紹介する😎ということが目的です。
Apollo ClientとRelayのどちらのツールも使用したことがない方には少し難しい内容になっている可能性があります。容赦ください。
私の状況
比較の前に私がどの程度Apollo ClientとRelayを理解しているかについて書きます。
まずRelayですが、使用歴1年半ほどです。Relayの設計方針の翻訳記事をこのブログに置いています。本番で使用していました。 Apollo Clientについても使用歴1年以上、本番で使用しています。Apollo Client用のツールであるNauを1年以上作っています。
Apollo Client
vs Relay
の概況
ざっくりとした話として、Apollo Client
or Relay
の技術選択について、簡単に触れていきたいと思います。
まず周りに配慮せず使用技術を決められるならRelayがおすすめです。 Relayの方が効率的で効果的で保守性が高い形でプログラムを書くことができます(というよりそのような形でしか書けません)。 ただし、チームメイトが使いこなせなかったり、Relayの想定する使い方と違うやり方をすると、途端に大変になります。ある程度自分で責任取れる人向けです。
一方Apollo Clientはプログラムを書いて動かすまでの敷居がとても低いです。また柔軟性・拡張性が高いのも特徴ですね。 ただし、保守性の高いプログラムを書こうとするとGraphQL Code Generatorなどの別プロダクトを併用しないといけなかったり、キャッシュの仕組みを詳細に理解しなければなりません。
※ 今回は触れませんが、どちらを使用する場合でもバックエンドのGraphQL APIはRelayのGraphQL Server Specificationに準拠しておいた方が後々幸せになれます。Apollo Clientを使う場合でも準拠したバックエンドを構築したほうが良いです。
Apollo Clientにいろいろ足しながらRelayと比較する
ここからはApollo Clientに様々なツールを足していきながらRelayと比較していきたいと思います。 実際Apollo Clientを使う時にそれだけで使用するということはほぼないので、「何を使ったらApollo ClientはRelayと同じぐらいの保守性や利便性が手に入れられるのか?」という観点で比較していきましょう。
Apollo Clientだけ
vs Relay
最初にそのままのApollo ClientとRelayとの比較について考えます。
残念ながらそのままApollo Clientを使うだけでは、TypeScriptの型も生成できませんし、書いたQueryが正しいのかも分かりません。すぐ壊れるので正直厳しい世界です。 Apollo Clientは簡単に始められるという利点はありますが、RelayとApolloの両方で本番運用をした経験がある人なら(この状況では)間違いなくRelayを推奨すると思います。 それほどApollo Clientだけで書いたプログラムは脆弱です。
Apollo Client + GraphQL Code Generator
vs Relay
Apollo ClientにGraphQL Code Generatorを併用することで、かなりまともな環境が手に入れられます。
GraphQL Code GeneratorはRelayのコンパイラと似たようなことをしてくれて、TypeScriptの型を出力したりQueryの静的解析をしてくれます。 若干GraphQL Code Generatorのプラグインに精通しておかないと何をどう使えばよいのか分からないこともありますが、1日かけてドキュメントを読み込めばなんとかなる範囲なので頑張りましょう。
この状況でApollo ClientがRelayに劣っている主な点は次のとおりです(Reactの最新機能への追随などは除きます。GraphQLクライアントとしての観点のみで考えます)。
保守性:
- フラグメントに閉じた変数などが使えないため、コロケーション(コンポーネントとフラグメントを近い場所に置いて運用すること)がうまくいかないです。コロケーションせずにスケーラブルなアプリケーションを作るのは中々難しいところがあります。
- キャッシュのバグは本当に解明しにくいのに、ちょっとリッチな機能を作ろうとするとキャッシュを直接弄る必要があるのでバグりやすいです。ページネーションやSubscriptionを使う時はキャッシュを弄りがちで、バグりがちです。
効率:
- Queryをリフェッチする時にフラグメント単位でリフェッチできないため、たびたびページのQuery全体を再実行する必要がありバックエンドから見て効率が悪いです。
- 仕組み上、Queryからデータを得ると全てのコンポーネントが再レンダリングされるためパフォーマンスチューニングが難しいです。
Apollo Client + GraphQL Code Generator + Nau
vs Relay
Apollo Client陣営にNauを参加させてみます。
NauはRelayにインスパイアされたApollo Client用のツール(GraphQL Code Generatorと一緒に使います)で、コロケーションを行うための各種ディレクティブや、フラグメント単位でのRefetch機能、バグりやすいキャッシュ制御のためのツールなどを提供しています。 Nauを使う場合はバックエンドがRelay GraphQL Server Specificationに準拠している必要があります。
NauはRelayの機能をGraphQL Code Generatorの上でApollo Client流に再現しているものと言えます。 Nauを使うことで先に述べたほとんどの課題は解決されます。残ったのは「Queryからデータを得ると全てのコンポーネントが再レンダリングされるためパフォーマンスチューニングが難しい」だけです。これもNauに入れたいところではありますが、まだ実装できていません。
まとめ
いろいろなツールをApollo Clientと一緒に使用することである程度Relayの機能をカバーできること、そしてそれらを標準搭載しているRelayのオールインワン感がお分かりいただけたと思います。
ちなみに、これを書いている私は、お客様のところで技術選定をする場合はRelayでのリスクを引き受けられないのでApollo Clientを最初に提案します 😇 自分でやる場合はRelay一択なのですが…。人間だもの。