なんだかんだここ半年くらいずっとCloudflare Workersを触ってます。
で、CDNエッジでコードが動くことはわかった。制約があることも、それなりに速いこともわかった。
で、これをどう扱っていくのが人類にとって良いんかな〜?みたいなことをずっと考えてた折に、VercelやらRemixが「これからはエッジだ!」(意訳)みたいなメッセージを出してて、ふふ〜んってなった今日このごろ。
We believe the modern Web is at the Edge and embraces the open Web platform.
https://vercel.com/blog/vercel-funding-series-d-and-valuationWe leveraged distributed systems at the edge instead of static builds.
https://remix.run/docs/en/v1/guides/philosophy
なのでここで現状を整理して、少しでも自分の思考の足しにしたいなーと。
エッジでSSR
SvelteKit w/ cloudflareアダプターとか、(Next.jsはまだCFWでSSRできないはずなので代わりに)Flareactとか、Remixとかがやろうとしてるやつ。
まあ実行環境だけを見るならば、従来のFaaSでやるよりは速いはずなので、諸々の制限さえ問題にならないなら別にええんではって感じ。
RemixのSSRに全振りする思想もわからんでもないし、エッジのおかげで妥協点のボーダーがいい感じになってきたのはあるかもしれない。RSCにしろ、Streaming SSRにしろ、従来のFaaSでやるよりかはエッジでやったほうが速くて嬉しいはずなので。
ただ、リクエストが実行環境に届くまでは速くなっても、そこから先が引き続きボトルネックになるならば、ユーザー体験としてはさほど変わりないのでは〜?と思ったりはする。
ことCFWに関して言えば、現状HTTPしかプロトコルが使えないので、DBまわりへのアクセスで余計に遅くなったりしないだろうか?データのあるNW内で完結したほうが速かったり?とか。そもそもエッジでSSRしまくるのが実用に足るものなのか?って話も、これから出てくる気はする。そもそもSSR・・話も引き続き。
ただDBもエッジ側によってくるのは順当な流れな気がしていて、CFWにはKVやDOがあるし、MarcrometaとかDBをエッジで!って言ってるサービスもある。
まぁセンシティブなデータまでエッジDBに載せる未来はあんまし想像つかんけど。
まぁこのあたりは巷のポエムに任せるとして、Cloudflare Workersだからこそできそうな、その他の使い方はないのか?ってことを考えてるってのが本題。
エッジでSSG+α
Cloudflare Workersには、`HTMLRewriter`っていう知られざるAPIがあって、それをなんとか活用する方法はないか?って考えてた。
https://developers.cloudflare.com/workers/runtime-apis/html-rewriter
これはその名の通りHTMLをリライトして返せるAPI。
// これを const htmlStr = await htmlResp.body(); return new Response(htmlStr.replace(/* ... */)); // こう書ける return new HTMLRewriter() .on("a", anchorRewriter).transform(htmlResp);
というように使える。
既存のHTMLがある前提のAPIになってて、たとえば事前に生成してKVに保存しておいたHTMLを取り出して加工して返すことができる。
jQueryライクなセレクタで対象の要素を見つけて、ピンポイントに書き換えができる。リライトするけど、ちゃんとストリーミングされたレスポンスがクライアントに返るところがポイント。チューニングがんばってるみたいな話も書いてあった。
A History of HTML Parsing at Cloudflare: Part 1
Low Output Latency (LOL)HTML parser/rewriter
なのでこれを使って、
- SSGで事前生成したHTMLでマーキングしておき、それをKVに保存しておく
- Workers Sitesでホスティングして、KVから取り出して返す
- ユーザー情報とか動的な情報を`HTMLRewriter`で埋め込み
- そのままでいいページはそのまま返す
っていうパターンができる気がしていて、これは実用的か?ってのを考えてる。SSR系フレームワークのアプローチの逆方向っぽいやつ。
SSR系のフレームワークを使ってその上でSSGする場合、不要なJSから逃げられないことが多い(サイズも実行も)のが現状なので、SSG系のフレームワークを使って、その上で動的部分を補うアプローチはどうだろうか、と。EleventyにしろAstroにしろ、動的部分はクライアントで処理するしかなくて不利で〜みたいなところをカバーできないかなーと。
- 完全に静的な部分: SSGしてあるからよい
- 初期表示でほしい動的な部分: リライトして対応、その上ストリーミングして返せる
- その後でいい動的な部分: SSGしたときに、(Partial)Hydrationするようにしたまま放置でよい
ってな感じのイメージ。(未検証)
考えられるデメリットは、
- SSGする層とリライトする層でコードが分散してしまう
- リライトした後のHydrationとかどうすんだ
- めちゃめちゃベンダーロックイン
- いやまぁ・・
という感じで、考えてはみたものの、そこまでお手軽ではなさそう。
けど、インタラクティブではないがLCPに大きく関わる・・っていうポイントに絞って使うのであれば、ナシではないかなーとも。まぁ手札の一枚として。
そもそもSSG(+ (Partial)Hydration)する構成を選んだ時点で、LCPやTTIに影響があるような動的部分はSSGによって解消されてる前提があるはず。そういう意味では、後から動的にしたい部分はおとなしくCSRする覚悟や判断があったはず。どうしても描画してから返したいなら、そもそもそれはSSGが不適合なサイトだったってだけ。
というわけで・・、可能性はあった気がしたけど、やはり動的部分がメインのサイトに関しては、
- SSRする
- エッジでやれるようになって速くなるならラッキー
もしくは、
- SSG + (Partial)Hydrationする
- 妥協点として
ってのが妥当な選択肢なんかなー。
現状のSSRはパフォーマンスに問題があると思うけど、ReactのSSRはそのへんも視野に入ってきてるぽいし。Svelteはまだそういう気配ないけど。そういえば既にStreaming SSRできるMarkoは、CFWで動くんやろうか?
New Suspense SSR Architecture in React 18 · Discussion #37 · reactwg/react-18 · GitHub
Async/streaming SSR renderer · Issue #958 · sveltejs/svelte · GitHub
ってもすぐには実用的なレベルにならんやろうし、Reactはそれ自体が相変わらず難しいし、SSR自体の技術的難易度が高いことにも変わりはないし、クライアントに落ちるJSのサイズも極力減らしたいし・・。
やっぱエッジでSSG+αもとい、PartialSSRなこの路線、もう少し探求してみるべき・・・?いやでも・・、みたいなことを悶々と考えてるという話でした。