Skip to content

Conversation

@irvinebroque
Copy link
Contributor

@irvinebroque irvinebroque commented Dec 30, 2025

Document microfrontend architecture using router workers and service bindings, including routing logic, path rewriting, asset handling, preloading, and deployment workflows.

Document microfrontend architecture using router workers and service bindings, including routing logic, path rewriting, asset handling, preloading, and deployment workflows.
@github-actions
Copy link
Contributor

github-actions bot commented Dec 30, 2025

This pull request requires reviews from CODEOWNERS as it changes files that match the following patterns:

Pattern Owners
/src/content/changelog/ @cloudflare/pm-changelogs, @cloudflare/pcx-technical-writing
/src/content/docs/workers/ @cloudflare/workers-docs, @GregBrimble, @irvinebroque, @mikenomitch, @korinne, @WalshyDev, @cloudflare/deploy-config, @cloudflare/pcx-technical-writing, @cloudflare/wrangler, @cloudflare/workers-runtime-1, @mattietk

Co-authored-by: Brayden Wilmoth <brayden.wilmoth@gmail.com>
Comment on lines +172 to +204
## 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.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## 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.
## Route Preloading
When `preload: true` is set on a static mount route, the router automatically preloads those routes to enable faster navigation. The router uses **browser-specific optimization** to provide the best performance for each browser:
### Chromium Browsers (Chrome, Edge, Opera, Brave)
For Chromium-based browsers, the router uses the **Speculation Rules API** - a modern, browser-native prefetching mechanism:
- Injects `<script type="speculationrules">` into the `<head>` element
- Browser handles prefetching automatically with optimal priority management
- Respects user preferences (battery saver, data saver modes)
- Uses per-document in-memory cache for faster access
- Not blocked by Cache-Control headers
- More efficient than JavaScript-based fetching
**Example injected speculation rules:**
```json
{
"prefetch": [
{
"urls": ["/app1", "/app2", "/dashboard"]
}
]
}

Other Browsers (Firefox, Safari)

For browsers that don't yet support the Speculation Rules API, the router falls back to a JavaScript-based preload script:

  • Injects <script src="/mount/__mf-preload.js" defer></script> into the <body> element
  • Script fetches preload routes after DOM loads
  • Uses external script (CSP-friendly) instead of inline JavaScript
  • Uses GET requests with credentials: "same-origin" and cache: "default"

Browser Detection:
The router automatically detects the browser from the User-Agent header and injects the appropriate preload mechanism. No configuration needed!

Limitations:

  • Only works for static mounts (no dynamic parameters)
  • Only preloads routes that are not the current route
  • Static mounts must have preload: true in their route configuration

Example Configuration:

{
	"routes": [
		{ "binding": "APP1", "path": "/app1", "preload": true },
		{ "binding": "APP2", "path": "/app2", "preload": true },
		{ "binding": "APP3", "path": "/:tenant/dashboard" } // Cannot preload (dynamic parameter)
	]
}

When a user visits /app1, the router will automatically preload /app2 (but not /app1 since that's the current route).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that didn't take the full suggestion because of backticks I imagine...

@Brayden
Copy link

Brayden commented Dec 31, 2025

Template added to our templates repo here: cloudflare/templates#877

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

product:workers Related to Workers product size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants