diff --git a/src/content/changelog/workers/2026-01-01-microfrontends.mdx b/src/content/changelog/workers/2026-01-01-microfrontends.mdx new file mode 100644 index 000000000000000..c3d7225cf51ecfb --- /dev/null +++ b/src/content/changelog/workers/2026-01-01-microfrontends.mdx @@ -0,0 +1,27 @@ +--- +title: Build microfrontend applications on Workers +description: Split a single application into independently deployable frontends using a router Worker and service bindings, enabling teams to develop and deploy features independently. +products: + - workers +date: 2026-01-01 +--- + +import { WranglerConfig } from "~/components"; + +You can now deploy microfrontends to Cloudflare, splitting a single application into smaller, independently deployable units that render as one cohesive application. This lets different teams using different frameworks develop, test, and deploy each microfrontend without coordinating releases. + +Microfrontends solve several challenges for large-scale applications: + +- **Independent deployments**: Teams deploy updates on their own schedule without redeploying the entire application +- **Framework flexibility**: Build multi-framework applications (for example, Astro, Remix, and Next.js in one app) +- **Gradual migration**: Migrate from a monolith to a distributed architecture incrementally + +Create a microfrontend project: + +[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://dash.cloudflare.com/?to=/:account/workers-and-pages/create?type=vmfe) + +This template automatically creates a router worker with pre-configured routing logic, and lets you configure [Service bindings](/workers/runtime-apis/bindings/service-bindings/) to Workers you have already deployed to your Cloudflare account. The router Worker analyzes incoming requests, matches them against configured routes, and forwards requests to the appropriate microfrontend via service bindings. The router automatically rewrites HTML, CSS, and headers to ensure assets load correctly from each microfrontend's mount path. The router includes advanced features like preloading for faster navigation between microfrontends, smooth page transitions using the View Transitions API, and automatic path rewriting for assets, redirects, and cookies. + +Each microfrontend can be a full-framework application, a static site with Workers Static Assets, or any other Worker-based application. + +Get started with the [microfrontends template](https://dash.cloudflare.com/?to=/:account/workers-and-pages/create?type=vmfe), or read the [microfrontends documentation](/workers/framework-guides/web-apps/microfrontends/) for implementation details. diff --git a/src/content/docs/workers/framework-guides/web-apps/microfrontends.mdx b/src/content/docs/workers/framework-guides/web-apps/microfrontends.mdx new file mode 100644 index 000000000000000..df0b6e0aebaa1ed --- /dev/null +++ b/src/content/docs/workers/framework-guides/web-apps/microfrontends.mdx @@ -0,0 +1,315 @@ +--- +pcx_content_type: concept +title: Microfrontends +sidebar: + order: 8 +description: Split a single application into independently deployable frontends, using a router worker and service bindings +--- + +import { WranglerConfig } from "~/components"; + +Microfrontends let you split a single application into smaller, independently deployable units that render as one cohesive application. Different teams using different technologies can develop, test, and deploy each microfrontend. + +Use microfrontends when you want to: + +- Enable many teams to deploy independently without coordinating releases +- Gradually migrate from a monolith to a distributed architecture +- Build multi-framework applications (for example, Astro, Remix, and Next.js in one app) + +## Get started + +Create a microfrontend project: + +[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://dash.cloudflare.com/?to=/:account/workers-and-pages/create?type=vmfe) + +This template automatically creates a router worker with pre-configured routing logic, and lets you configure [Service bindings](/workers/runtime-apis/bindings/service-bindings/) to Workers you have already deployed to your Cloudflare account. + +## How it works + +```mermaid +graph LR + A[Browser Request] --> B[Router Worker] + B -->|Service Binding| C[Microfrontend A] + B -->|Service Binding| D[Microfrontend B] + B -->|Service Binding| E[Microfrontend C] +``` + +The router worker: + +1. Analyzes the incoming request path +2. Matches it against configured routes +3. Forwards the request to the appropriate microfrontend via service binding +4. Rewrites HTML, CSS, and headers to ensure assets load correctly +5. Returns the response to the browser + +Each microfrontend can be: + +- A full-framework application (Next.js, SvelteKit, Astro, etc.) +- A static site with [Workers Static Assets](/workers/static-assets/) +- Built with different frameworks and technologies + +## Routing logic + +The router worker uses a `ROUTES` [environment variable](/workers/configuration/environment-variables/) to determine which microfrontend handles each path. Routes are matched by specificity, with longer paths taking precedence. + +Example `ROUTES` configuration: + +```json +{ + "routes": [ + { "path": "/app-a", "binding": "MICROFRONTEND_A", "preload": true }, + { "path": "/app-b", "binding": "MICROFRONTEND_B", "preload": true }, + { "path": "/", "binding": "MICROFRONTEND_HOME" } + ], + "smoothTransitions": true +} +``` + +Each route requires: + +- `path`: The mount path for the microfrontend (must be distinct from other routes) +- `binding`: The name of the service binding in your [Wrangler configuration file](/workers/wrangler/configuration/) +- `preload` (optional): Whether to prefetch this microfrontend for faster navigation + +When a request comes in for `/app-a/dashboard`, the router: + +1. Matches it to the `/app-a` route +2. Forwards the request to `MICROFRONTEND_A` +3. Strips the `/app-a` prefix, so the microfrontend receives `/dashboard` + +The router includes path matching logic that supports: + +```typescript +// Static paths +{ "path": "/dashboard" } + +// Dynamic parameters +{ "path": "/users/:id" } + +// Wildcard matching (zero or more segments) +{ "path": "/docs/:path*" } + +// Required segments (one or more segments) +{ "path": "/api/:path+" } +``` + +## Path rewriting + +The router worker uses [HTMLRewriter](/workers/runtime-apis/html-rewriter/) to automatically rewrite HTML attributes to include the mount path prefix, ensuring assets load from the correct location. + +When a microfrontend mounted at `/app-a` returns HTML: + +```html + + + +``` + +The router rewrites it to: + +```html + + + +``` + +The rewriter handles these attributes across all HTML elements: + +- `href`, `src`, `poster`, `action`, `srcset` +- `data-*` attributes like `data-src`, `data-href`, `data-background` +- Framework-specific attributes like `astro-component-url` + +The router only rewrites paths that start with configured asset prefixes to avoid breaking external URLs: + +```javascript +// Default asset prefixes +const DEFAULT_ASSET_PREFIXES = [ + "/assets/", + "/static/", + "/build/", + "/_astro/", + "/fonts/", +]; +``` + +Most frameworks work with the default prefixes. For frameworks with different build outputs (like Next.js which uses `/_next/`), you can configure custom prefixes using the `ASSET_PREFIXES` [environment variable](/workers/configuration/environment-variables/): + +```json +["/_next/", "/public/"] +``` + +## Asset handling + +The router also rewrites CSS files to ensure `url()` references work correctly. When a microfrontend mounted at `/app-a` returns CSS: + +```css +.hero { + background: url(/assets/hero.jpg); +} + +.icon { + background: url("/static/icon.svg"); +} +``` + +The router rewrites it to: + +```css +.hero { + background: url(/app-a/assets/hero.jpg); +} + +.icon { + background: url("/app-a/static/icon.svg"); +} +``` + +The router also handles: + +- **Redirect headers**: Rewrites `Location` headers to include the mount path +- **Cookie paths**: Updates `Set-Cookie` headers to scope cookies to the mount path + +## Preloading + +The router can generate a preload script that prefetches other microfrontends in the background, improving navigation performance between different parts of your application. + +When you set `"preload": true` on a route, the router: + +1. Generates a `/__mf-preload.js` script +2. Injects it into HTML responses +3. Prefetches configured microfrontends after page load + +Example preload script (automatically generated): + +```javascript +// Injected by router worker +const routes = ["/app-a", "/app-b"]; +const run = () => { + for (const p of routes) { + fetch(p, { + method: "GET", + credentials: "same-origin", + cache: "default", + }).catch(() => {}); + } +}; + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", run, { once: true }); +} else { + run(); +} +``` + +This allows browsers to fetch and [cache](/cache/) resources from other microfrontends before users navigate to them, resulting in faster transitions. + +## Smooth transitions + +You can enable smooth page transitions between microfrontends using the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API). + +To enable smooth transitions, set `"smoothTransitions": true` in your `ROUTES` configuration: + +```json +{ + "routes": [ + { "path": "/app-a", "binding": "MICROFRONTEND_A" }, + { "path": "/app-b", "binding": "MICROFRONTEND_B" } + ], + "smoothTransitions": true +} +``` + +The router automatically injects CSS into HTML responses: + +```css +@supports (view-transition-name: none) { + ::view-transition-old(root), + ::view-transition-new(root) { + animation-duration: 0.3s; + animation-timing-function: ease-in-out; + } + main { + view-transition-name: main-content; + } + nav { + view-transition-name: navigation; + } +} +``` + +This feature only works in browsers that support the View Transitions API. Browsers without support will navigate normally without animations. + +## Add a new microfrontend + +To add a new microfrontend to your application after initial setup: + +1. **Create and deploy the new microfrontend worker** + + Deploy your new microfrontend as a separate Worker. This can be a [framework application](/workers/framework-guides/) (Next.js, Astro, etc.) or a static site with [Workers Static Assets](/workers/static-assets/). + +2. **Add a [service binding](/workers/runtime-apis/bindings/service-bindings/) in your router's Wrangler configuration file** + + + ```toml + [[services]] + binding = "MICROFRONTEND_C" + service = "my-new-microfrontend" + ``` + + +3. **Update the `ROUTES` environment variable** + + Add your new route to the `ROUTES` configuration: + + ```json + { + "routes": [ + { "path": "/app-a", "binding": "MICROFRONTEND_A", "preload": true }, + { "path": "/app-b", "binding": "MICROFRONTEND_B", "preload": true }, + { "path": "/app-c", "binding": "MICROFRONTEND_C", "preload": true }, + { "path": "/", "binding": "MICROFRONTEND_HOME" } + ] + } + ``` + +4. **Redeploy the router worker** + + ```sh + npx wrangler deploy + ``` + +Your new microfrontend is now accessible at the configured path (for example, `/app-c`). + +## Local development + +During development, you can test your microfrontend architecture locally using Wrangler's service binding support. Run the router Worker locally using `wrangler dev`, and then in separate terminals run each of the microfrontends. + +If you only need to work on one of the microfrontends, you can run the others remotely using [remote bindings](/workers/development-testing/#remote-bindings), without needing to have access to the source code or run a local dev server. + +For each microfrontend you want to run remotely while in local dev, configure its service binding with the remote flag: + + +```json +{ +"services": [ + { + "binding": "", + "service": "", + "remote": true + } +] +} +``` + + +## Deployment + +Each microfrontend can be deployed independently without redeploying the router or other microfrontends. This enables teams to: + +- Deploy updates on their own schedule +- Roll back individual microfrontends without affecting others +- Test and release features independently + +When you deploy a microfrontend worker, the router automatically routes requests to the latest version via the service binding. No router changes are required unless you are adding new routes or updating the `ROUTES` configuration. + +To deploy to production, you can use [custom domains](/workers/configuration/routing/custom-domains/) for your router worker, and configure [Workers Builds](/workers/ci-cd/builds/) for continuous deployment from your Git repository.