Web フロントエンド開発の歴史を学ぶ
構成としては回帰してるんだよね。
クライアントサイドから form で API サーバにリクエストが送信されたらサーバ側でで DB からデータを取得してテンプレートエンジンに埋め込んで HTML 作ってクライアントに返すってのを Remix や Next.js で実現してる。エッジ環境が進化した状態で。
ここで重要なのは、(かなりわかりづらいですが) クライアントとサーバーの見かけ上の関係性がAjax以前の時代に戻っている ということです。
クライアントサイドの fetch()
がなくても問題ないようにしている。これまで SPA でページ読み込み時に fetch していた役割を Remix ではサーバ側でやってくれる(これは BFF と呼んでよいのか?)。
自分の中では、昔 Django とか Express とかでテンプレートエンジンでサーバ側で HTML を生成していた時代の技術が、現代版でエッジ環境(サーバ側)で実現できるようにしたのが Remix、という理解。
注目すべき点として、この挙動はオプションではなくデフォルトであるということです。実際に触ってみるとわかるのですが、RemixもApp Routerも、基本的にクライアントサイドで fetch() を直接使わせる気がかなり少なめです。そもそもApp RouterではすべてのコンポーネントがRSCとして動作するため、よほど明示的に "use client" を付けた場合にしかブラウザ側でJavaScriptが実行されません。Remixも理論上はブラウザ上で fetch() を実行することは不可能ではないはずです[4]が、代替としてuseFetcher()を整備して、任意のタイミングで任意のパスの loader や action を呼び出せるようにしている程度には、 fetch() がなくても問題ないようにしています。
Remix の構造の整理:「BFF」ってどこのことを言っている?
このツイートが参考になった。
表現が正しいかはわからないけど時代を整理するとこんな感じ
- テンプレートエンジン時代(データフェッチはサーバーサイドが主)
- HTML → モノリスなサーバサイドのサービス(Rails、ASP.NET、Django、Express など)
- HTML → API Gateway → サーバサイドのサービス群(Microservices)
- SPA 時代(データフェッチはクライアントサイドが主)
- HTML(SPA、React.js) → API Gateway → サーバサイドのサービス群
- HTML(SPA、React.js(Next.js Pages Router に含まれる)) → BFF(Next.js Pages Router) → API Gateway → サーバサイドのサービス群
- Remix、Next.js API Router 時代(データフェッチはサーバーサイドが主)
- HTML → BFF(Remix, Next.js API Router) → API Gateway → サーバサイドのサービス群
多分この記事で言及している Remix の「BFF」と SPA 時代の「BFF」の役割が変わってきていると解釈。
多分この頃自分は「テンプレートエンジン時代」と「SPA 時代」の間にいたのかな。たしか React.js で SPA、Django の API モード(Rails の API モードみたいなやつ?)で開発してた記憶。
もちろんクライアントサイドからの BFF へのリクエストが 0 になるわけではなく、form とかで非同期に(ユーザがボタンを押したタイミングなどに) BFF へのリクエストが送信されたときは BFF 側で loader を使ってデータを作り、それをクライアントサイドに返してそれによりクライアントサイドの表示をページの再ロードなしで更新する。内部では ajax が使われている。
例えば、Form
コンポーネントの裏側では fetch
API が使われているが、ユーザが直接 fetch
を呼び出したり、fetch
のラッパー(axios など)を呼び出すことがなくてもよいように隠蔽された設計になっている。
最後に、RemixもApp Routerも、見かけ上、Ajaxを意識する場所が激減していますが、フレームワークの内部実装としてはAjaxをむしろ多用していますので、「Ajax終了のお知らせ」みたいな感想は持たないようにお願いします。Ajax濫用の時代は終わるかもですが、Ajaxはこれからも私たちの大切な基礎技術の一つです。
これはたしかに
ところでさあ、筆者はモバイルアプリ出身だから考えちゃうんだけどさあ、「クライアントがAPIサーバーと直接何回も通信するのはパフォーマンスを損なう」っていう課題はさあ、モバイルアプリにも刺さるんですよ。モバイルアプリにはBFFみたいな頼れる味方がいないので、PESPA的なアプローチでの改善はできないんですよ。
モバイルアプリで通信によるパフォーマンス低下を改善するには、GraphQL的なアプローチしか残されていないのか……?