Cloudflare Workersとマイクロフロントエンド
Cloudflareブログで興味深い記事が投稿されていたので読んだ。
趣旨としてはマイクロフロントエンドアーキテクチャのFragments組成をブラウザからではなくEdgeサーバーとSSRのレイヤーで実現する、というものだと思う。
マイクロサービスアーキテクチャのAPI Gateway / Backends for Frontendsパターンのうちブラウザアプリケーションに限定して拡張したものという理解をした。
Fragments組成
例えばこんな感じに画面の一部を描画するエンドポイントがある
- https://cloud-gallery-header.web-experiments.workers.dev/
- https://cloud-gallery-footer.web-experiments.workers.dev/
これら1つ1つをCloudflare WorkersのServiceにして、ルートとなるmainサービスがServer-to-Serverで取得し1つのページとして返す
Cloud Gallery
サンプルとして https://cloud-gallery.web-experiments.workers.dev/ のソースコードが以下で公開されている
これをCloudflare Workersにデプロイすると計6つのServiceになってアップロードされ、Topページにアクセスするだけで内部的にリクエストが発生して呼び出されている。
画像の遅延読み込み
ヘッダに画像リソースを読み込むタイミングを遅延されて非同期な画面描画をシュミレートできる機能がある。
これはどういうことをしているのか見てみたら、Lagコンポーネントの中でqwikのResourceコンポーネント でラップしてsleepした後にDOMに追加ように書かれていた。
// 呼び出し側
<Lag delay={delay}>
<Image src={img.url} />
</Lag>
実際の用途ではこのResorceのsleepの部分が外部APIへのfetchに置き換わることでイメージできそう。
サービス分割
npmのworkspaceを使ったモノレポになっていて npm run deploy
すると各自wrangler publish
されて発射される。
独立してデプロイ可能な部分がマイクロフロントエンドアーキテクチャっぽいなと思った(他のPocと比較して)。
どうやって組成されているのか
まずmainサービスのエントリーポントからqwikのrenderToStream()を通じてRootコンポーネントがStreams APIを使ってレンダリングされてHTTPレスポンスとして返される。
RootコンポーネントにはqwikのSSRStreamコンポーネント(まだドキュメントに説明がない)でラップされた各サービスへ向けたfetchを含む子コンポーネントFragmentPlaceholderが含まれる。
サービス間でfetchをしている部分の実体はfragmentHelpers.tsxにまとまっている。
このfetchはHTTP RequestのfetchではなくCloudflare WorkersのService bindingsで定義された呼び出し先になっている。
疑問(1): Cloudflare Workersでないといけないの?
前述のとうりマイクロサービスアーキテクチャの一形態というだけなのでWebサーバーがHTML返してきて、その子要素が別のサーバーに分割されていれば要件は満せそう(いわゆるSSIやServer-side template composition)。
Cloudflare曰くエッジサーバーのユーザーからの距離の利点とかWorkers諸機能の恩恵でオーバーヘッド減らせるよということらしい。
疑問(2): Qwik必要?
既存のマイクロフロントエンドアーキテクチャのクライアントサイドで組成するものに対して問題点を指摘したいのでブラウザ上でのフットプリントが小さいQwikを使ったのだと思う。Svelteなどでも同じデモは作れそう。
Fragment間でイベントを伝達して結果を適用するなどの実際にありそうなケースでどうなるのかよく分からないしuseContextProvider()
やuseEnvData()
がどう機能するのかも理解できてないので、他にQwikである理由もあるのかもしれない。
他にはHotwireはエンドポイントごとにHTMLを返してきてSSRで結合してくる部分は似ているけど、デプロイ独立していないしクライアントサイド処理にも比重があるのでフォーカスしている問題が異なる。
Discussion