Cloudflareプラットフォームでの垂直マイクロフロントエンド構築
Cloudflareは、URLパスごとに独立したCloudflare Workersを割り当てることで、チームが完全な自律性を持って開発・デプロイできる「垂直マイクロフロントエンド」の新テンプレートを発表しました。
キーポイント
垂直マイクロフロントエンドの概念
従来の水平分割ではなく、URLパスごとにアプリケーションを分割し、各チームが特定のパス(例:/blog、/dash)のフロントエンドからCI/CDまでの全スタックを所有・管理するアーキテクチャパターンです。
Cloudflare Workersによる実現
単一ドメインに複数の独立したCloudflare Workersをマッピングする新テンプレートを提供し、マーケティングサイト、ドキュメント、ダッシュボードなどを別々のチームが自律的に開発・デプロイできるようにします。
開発チームの課題解決
異なるフレームワークの使用(例:AstroとReact)、モノリシックコードベースでの回帰問題、チーム間の依存関係を解消し、完全な自律性と所有権を持った開発を可能にします。
具体的な適用例
/(マーケティング)、/docs(ドキュメント)、/blog(ブログ)、/dash(ダッシュボード)といったパス割り当てや、/dash/product-aと/dash/product-bのようにさらに細かいサブパスごとに異なるWorkerを割り当てることも可能です。
視覚的統一の実現方法
CSS View Transitionsを使用することで、異なるプロジェクト間のナビゲーションをシームレスにし、単一のアプリケーションのように感じさせる。
内部での実践例
Cloudflareダッシュボードでは、コアダッシュボードとZeroTrust製品が別々のプロジェクトだが、パスベースのルーティングと視覚的統一で統合された体験を提供している。
CSS View Transitionsによるナビゲーションの連続性
CSS View Transitionsを使用して、ページ遷移時にナビゲーション要素を保持し、白い空白ページを防ぐことで、シームレスなユーザー体験を実現する。
影響分析・編集コメントを表示
影響分析
この発表は、大規模開発組織におけるフロントエンド開発の課題を解決する実用的なソリューションを提供します。特に、複数チームが異なる技術スタックで並行開発する際の自律性と統合性の両立に貢献し、クラウドネイティブなフロントエンド開発の進化を示しています。
編集コメント
技術的な深みと実用性が高い内容ですが、AI業界との直接的な関連性は限定的です。フロントエンド開発の効率化とチーム構造の進化に焦点を当てた実践的な技術記事と言えます。
Cloudflareプラットフォーム上での垂直マイクロフロントエンドの構築
Brayden Wilmoth
更新: PT午前6時55分
本日、垂直マイクロフロントエンド(VMFE)向けの新しいWorkerテンプレートを紹介します。このテンプレートを使用すると、複数の独立したCloudflare Workerを単一ドメインにマッピングでき、チームが完全なサイロ状態で作業(マーケティングサイト、ドキュメント、ダッシュボードを独立してリリース)しながら、ユーザーには単一のシームレスなアプリケーションとして提示することが可能になります。
ほとんどのマイクロフロントエンドアーキテクチャは「水平型」であり、単一ページの異なる部分が異なるサービスから取得されることを意味します。垂直マイクロフロントエンドは、URLパスによってアプリケーションを分割するという異なるアプローチを取ります。このモデルでは、/blogパスを担当するチームは、単なるコンポーネントだけでなく、そのルートに対するフレームワーク、ライブラリ選択、CI/CDなど、垂直スタック全体を所有します。パスまたは一連のパスのスタック全体を所有することで、チームは自身の作業に対する真の所有権を持ち、自信を持ってリリースすることができます。
組織が成長するにつれて、異なるフレームワークが様々なユースケースに対応するという問題に直面します。例えば、マーケティングサイトにはAstroが、ダッシュボードにはReactがより適しているかもしれません。あるいは、多くのチームが集合体としてリリースを行うモノリシックなコードベースがあるとします。複数のチームによる新機能追加の更新が、単一のチームが引き起こしたリグレッションのために、苛立たしいほどロールバックされることがあります。技術的な実装詳細をユーザーから隠蔽し、チームが自身のドメインを完全な自律性とコントロールのもとで結束力のあるユーザー体験をリリースするには、どうすればよいでしょうか?
垂直マイクロフロントエンドがその答えとなり得ます。それらがどのように開発者の課題を解決するのか、詳しく探ってみましょう。
垂直マイクロフロントエンドとは何か?
垂直マイクロフロントエンドとは、単一の独立したチームが、ユーザーインターフェースからCI/CDパイプラインまで、アプリケーション機能のスライス全体を所有するアーキテクチャパターンです。これらのスライスは、個々のWorkerを特定のパスに関連付けることができるドメイン上のパスによって定義されます。
/ = マーケティング
/docs = ドキュメント
/blog = ブログ
/dash = ダッシュボード
さらに一歩進んで、ダッシュボードなど、より細かいサブパスへのWorkerの関連付けに焦点を当てることもできます。ダッシュボード内では、URLパスに深さを追加することで(例: /dash/product-a)、様々な機能や製品をセグメント化することが多いでしょう。
垂直マイクロフロントエンドでは、以下のような構成も可能です。
/dash/product-a = WorkerA
/dash/product-b = WorkerB
上記の各パスは、互いに共有コードが一切ない独自のフロントエンドプロジェクトです。product-aのチームは、product-bのチームが何をしているか、あるいはどのフレームワークを使用しているかを気にする必要はありません。これにより、チームは完全な自律性を持ち、自身の製品をリリースすることができます。
これで、エンドツーエンドで自身のコードを所有できるようになりました。しかし今度は、これらの別々のプロジェクトを結合する方法を見つけ、さらに、それらが統一された体験であるかのように感じさせる必要があります。
Cloudflare自身もこの課題を経験しています。ダッシュボードには多くの個別チームが自身の製品を所有しており、チームは自身のコントロール外で行われた変更が、ユーザーの製品体験にどのように影響するかと対峙しなければなりません。
社内では、現在、自社のダッシュボードに対して同様の戦略を使用しています。ユーザーがコアダッシュボードからZeroTrust製品に移動するとき、実際にはそれらは2つの完全に別々のプロジェクトであり、ユーザーは単にそのパス /:accountId/one によってそのプロジェクトにルーティングされているだけです。
視覚的に統一された体験
これらの個々のプロジェクトを結合して、統一された体験であるかのように感じさせることは、思っているほど難しくありません。ほんの数行のCSSの魔法で実現できます。絶対に避けたいのは、実装詳細や内部決定をユーザーに漏らしてしまうことです。このユーザー体験を一つの結束力のあるフロントエンドのように感じさせることができなければ、ユーザーに対して重大な不利益を与えたことになります。
この手品を成功させるために、ビュートランジションとドキュメントのプリロードがどのように機能するかを少し理解する旅に出ましょう。
ビュートランジション
エンドユーザーにスムーズに感じさせながら、2つの異なるページ間をシームレスに遷移させたい場合、ビュートランジションは非常に有用です。ページ上の特定のDOM要素を次のページが表示されるまで維持するように定義し、あらゆる変更がどのように処理されるかを定義することで、マルチページアプリケーションにとって非常に強力なキルト縫い合わせツールとなります。
ただし、様々な垂直マイクロフロントエンドをあえて異なるものに感じさせる方が、より受け入れられる場合もあるかもしれません。例えば、マーケティングサイト、ドキュメント、ダッシュボードがそれぞれ独自に定義されている場合です。ユーザーはこれら3つの部分間を移動する際に、すべてが結束力があることを期待しないでしょう。しかし…ダッシュボード(例: /dash/product-a と /dash/product-b)のような個々の体験内に垂直スライスを導入することを決めた場合は、それらを統一されたものとして感じさせる必要があります。
さて、話はここまでにして、作業に取り掛かりましょう。2つの別々のプロジェクトをユーザーにとって1つのように感じさせるのは手間がかからないと述べましたが、もしCSSビュートランジションについてまだ聞いたことがなければ、これから驚かせることになるでしょう。
シングルページアプリケーション(SPA)であれマルチページアプリケーション(MPA)であれ、異なるビュー間のアニメーション遷移を1つのもののように感じさせることができると言ったらどうでしょうか?ビュートランジションが追加される前は、2つの異なるWorkerが所有するページ間を移動すると、次のページ全体のレンダリングが始まるまでの数百ミリ秒の間、ブラウザ内の空白の白い画面が間の読み込み状態として表示されていました。ページは結束力があるとは感じられず、確かにシングルページアプリケーションのようには感じられませんでした。
各サイト間で複数のナビゲーション要素として表示される。
要素を維持させ、空白の白いページを見る代わりにしたい場合は、CSSビュートランジションを定義することで実現できます。以下のコードでは、ビュートランジションイベントが発生しようとしているときに、現在のドキュメントページに対して nav 要素を維持するように指示しています。
突然、2つの異なるWorkerが1つのように感じられます。
@supports (view-transition-name: none) {
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.3s;
animation-timing-function: ease-in-out;
}
nav {
view-transition-name: navigation;
}
}
3つの異なるサイト間で単一のナビゲーション要素として表示される。
2つのページ間の遷移をシームレスに見せるだけでなく、クライアントサイドSPAのように瞬時に感じさせたい場合もあります。現在、FirefoxとSafariはSpeculation Rulesをサポートしていませんが、Chrome/Edge/Operaはこの比較的新しい参入者をサポートしています。speculation rules APIは、将来のナビゲーション、特にドキュメントURLのパフォーマンスを向上させるために設計されており、マルチページアプリケーションをよりシングルページアプリケーションのように感じさせます。
コードに分解すると、定義する必要があるのは特定の形式のスクリプトルールであり、サポートするブラウザに対して、ウェブアプリケーションに接続されている他の垂直スライス(おそらく何らかの共有ナビゲーションを介してリンクされている)をどのようにプリフェッチするかを指示します。
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["https://product-a.com", "https://product-b.com"],
"requires": ["anonymous-client-ip-when-cross-origin"],
"referrer_policy": "no-referrer"
}
]
}
</script>
これにより、アプリケーションは他のマイクロフロントエンドをプリフェッチし、メモリ内キャッシュに保持するので、それらのページに移動する場合、ほぼ瞬時に感じられます。
明確に区別できる垂直スライス(マーケティング、ドキュメント、ダッシュボード)には、おそらくこれは必要ないでしょう。なぜなら、ユーザーはそれらの間で少しの読み込みを期待するからです。しかし、特定の可視体験内(例: ダッシュボードページ内)で垂直スライスが定義されている場合は、使用することが強く推奨されます。
ビュートランジションとSpeculation Rulesによって、完全に異なるコードリポジトリを結合し、あたかもシングルページアプリケーションから提供されているかのように感じさせることができます。私に言わせれば、驚くべきことです。
ゼロ設定リクエストルーティング
次に、複数のWorkerを単一ドメインでホストするメカニズムが必要です。
原文を表示
Building vertical microfrontends on Cloudflare’s platform
Brayden Wilmoth
Updated at 6:55 a.m. PT
Today, we’re introducing a new Worker template for Vertical Microfrontends (VMFE). This template allows you to map multiple independent Cloudflare Workers to a single domain, enabling teams to work in complete silos — shipping marketing, docs, and dashboards independently — while presenting a single, seamless application to the user.
Most microfrontend architectures are "horizontal", meaning different parts of a single page are fetched from different services. Vertical microfrontends take a different approach by splitting the application by URL path. In this model, a team owning the /blog path doesn't just own a component; they own the entire vertical stack for that route – framework, library choice, CI/CD and more. Owning the entire stack of a path, or set of paths, allows teams to have true ownership of their work and ship with confidence.
Teams face problems as they grow, where different frameworks serve varying use cases. A marketing website could be better utilized with Astro, for example, while a dashboard might be better with React. Or say you have a monolithic code base where many teams ship as a collective. An update to add new features from several teams can get frustratingly rolled back because a single team introduced a regression. How do we solve the problem of obscuring the technical implementation details away from the user and letting teams ship a cohesive user experience with full autonomy and control of their domains?
Vertical microfrontends can be the answer. Let’s dive in and explore how they solve developer pain points together.
What are vertical microfrontends?
A vertical microfrontend is an architectural pattern where a single independent team owns an entire slice of the application’s functionality, from the user interface all the way down to the CI/CD pipeline. These slices are defined by paths on a domain where you can associate individual Workers with specific paths:
/ = Marketing /docs = Documentation /blog = Blog /dash = Dashboard
We could take it a step further and focus on more granular sub-path Worker associations, too, such as a dashboard. Within a dashboard, you likely segment out various features or products by adding depth to your URL path (e.g. /dash/product-a
Now with vertical microfrontends, we could also have the following:
/dash/product-a = WorkerA /dash/product-b = WorkerB
Each of the above paths are their own frontend project with zero shared code between them. The product-a
You can now own your own code from end to end. But now we need to find a way to stitch these separate projects together, and even more so, make them feel as if they are a unified experience.
We experience this pain point ourselves here at Cloudflare, as the dashboard has many individual teams owning their own products. Teams must contend with the fact that changes made outside their control impact how users experience their product.
Internally, we are now using a similar strategy for our own dashboard. When users navigate from the core dashboard into our ZeroTrust product, in reality they are two entirely separate projects and the user is simply being routed to that project by its path /:accountId/one
Visually unified experiences
Stitching these individual projects together to make them feel like a unified experience isn’t as difficult as you might think: It only takes a few lines of CSS magic. What we absolutely do not want to happen is to leak our implementation details and internal decisions to our users. If we fail to make this user experience feel like one cohesive frontend, then we’ve done a grave injustice to our users.
To accomplish this sleight of hand, let us take a little trip in understanding how view transitions and document preloading come into play.
View transitions
When we want to seamlessly navigate between two distinct pages while making it feel smooth to the end user, view transitions are quite useful. Defining specific DOM elements on our page to stick around until the next page is visible, and defining how any changes are handled, make for quite the powerful quilt-stitching tool for multi-page applications.
There may be, however, instances where making the various vertical microfrontends feel different is more than acceptable. Perhaps our marketing website, documentation, and dashboard are each uniquely defined, for instance. A user would not expect all three of those to feel cohesive as you navigate between the three parts. But… if you decide to introduce vertical slices to an individual experience such as the dashboard (e.g. /dash/product-a
/dash/product-b
Okay, enough talk — let’s get to work. I mentioned it was low-effort to make two separate projects feel as if they were one to a user, and if you have yet to hear about CSS View Transitions then I’m about to blow your mind.
What if I told you that you could make animated transitions between different views — single-page app (SPA) or multi-page app (MPA) — feel as if they were one? Before any view transitions are added, if we navigate between pages owned by two different Workers, the interstitial loading state would be the white blank screen in our browser for some few hundred milliseconds until the full next page began rendering. Pages would not feel cohesive, and it certainly would not feel like a single-page application.
Appears as multiple navigation elements between each site.
If we want elements to stick around, rather than seeing a white blank page, we can achieve that by defining CSS View Transitions. With the code below, we’re telling our current document page that when a view transition event is about to happen, keep the nav
All of a sudden, two different Workers feel like one.
@supports (view-transition-name: none) { ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.3s; animation-timing-function: ease-in-out; } nav { view-transition-name: navigation; } }
Appears as a single navigation element between three distinct sites.
Transitioning between two pages makes it look seamless — and we also want it to feel as instant as a client-side SPA. While currently Firefox and Safari do not support Speculation Rules, Chrome/Edge/Opera do support the more recent newcomer. The speculation rules API is designed to improve performance for future navigations, particularly for document URLs, making multi-page applications feel more like single-page applications.
Breaking it down into code, what we need to define is a script rule in a specific format that tells the supporting browsers how to prefetch the other vertical slices that are connected to our web application — likely linked through some shared navigation.
With that, our application prefetches our other microfrontends and holds them in our in-memory cache, so if we were to navigate to those pages it would feel nearly instant.
You likely won’t require this for clearly discernible vertical slices (marketing, docs, dashboard) because users would expect a slight load between them. However, it is highly encouraged to use when vertical slices are defined within a specific visible experience (e.g. within dashboard pages).
Between View Transitions and Speculation Rules, we are able to tie together entirely different code repositories to feel as if they were served from a single-page application. Wild if you ask me.
Zero-config request routing
Now we need a mechanism to host multiple applications, and a method to stitch them together as requests stream in. Defining a single Cloudflare Worker as the “Router” allows a single logical point (at the edge) to handle network requests and then forward them to whichever vertical microfrontend is responsible for that URL path. Plus it doesn’t hurt that then we can map a single domain to that router Worker and the rest “just works.”
Service bindings
If you have yet to explore Cloudflare Worker service bindings, then it is worth taking a moment to do so.
Service bindings allow one Worker to call into another, without going through a publicly-accessible URL. A Service binding allows Worker A to call a method on Worker B, or to forward a request from Worker A to Worker. Breaking it down further, the Router Worker can call into each vertical microfrontend Worker that has been defined (e.g. marketing, docs, dashboard), assuming each of them were Cloudflare Workers.
Why is this important? This is precisely the mechanism that “stitches” these vertical slices together. We’ll dig into how the request routing is handling the traffic split in the next section. But to define each of these microfrontends, we’ll need to update our Router Worker’s wrangler definition, so it knows which frontends it’s allowed to call into.
{ "$schema": "./node_modules/wrangler/config-schema.json", "name": "router", "main": "./src/router.js", "services": [ { "binding": "HOME", "service": "worker_marketing" }, { "binding": "DOCS", "service": "worker_docs" }, { "binding": "DASH", "service": "worker_dash" }, ] }
Our above sample definition is defined in our Router Worker, which then tells us that we are permitted to make requests into three separate additional Workers (marketing, docs, and dash). Granting permissions is as simple as that, but let’s tumble into some of the more complex logic with request routing and HTML rewriting network responses.
Request routing
With knowledge of the various other Workers we are able to call into if needed, now we need some logic in place to know where to direct network requests when. Since the Router Worker is assigned to our custom domain, all incoming requests hit it first at the network edge. It then determines which Worker should handle the request and manages the resulting response.
The first step is to map URL paths to associated Workers. When a certain request URL is received, we need to know where it needs to be forwarded. We do this by defining rules. While we support wildcard routes, dynamic paths, and parameter constraints, we are going to stay focused on the basics — literal path prefixes — as it illustrates the point more clearly.
In this example, we have three microfrontends:
/ = Marketing /docs = Documentation /dash = Dashboard
Each of the above paths need to be mapped to an actual Worker (see our wrangler definition for services in the section above). For our Router Worker, we define an additional variable with the following data, so we can know which paths should map to which service bindings. We now know where to route users as requests come in! Define a wrangler variable with the name ROUTES and the following contents:
{ "routes":[ {"binding": "HOME", "path": "/"}, {"binding": "DOCS", "path": "/docs"}, {"binding": "DASH", "path": "/dash"} ] }
Let’s envision a user visiting our website path /docs/installation
Why does it drop the /docs
Splitting our various frontend services with URL paths (e.g. /docs
Say our documentation website has an image tag in the response

https://website.com/docs/
Only when our services are accessed through our Router Worker do we need to do some HTML rewriting of absolute paths so our returned browser response references valid assets. In practice what happens is that when a request passes through our Router Worker, we pass the request to the correct Service Binding, and we receive the response from that. Before we pass that back to the client, we have an opportunity to rewrite
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み