Skip to content

Cloudflare Workers

Pageflare ships a WebAssembly (WASM) build of its core optimization engine. You can import this WASM module directly into a Cloudflare Worker and run it as an edge middleware — intercepting HTML responses and rewriting them before they reach the user.

When this makes sense:

  • You are proxying a backend that generates HTML dynamically and you cannot run a build step.
  • You want to apply optimizations to cached Cloudflare responses without rebuilding.
  • You need per-request control over which optimizations apply (e.g., based on headers or cookies).

When to prefer the CLI approach:

  • Your site is a static build (Astro, Hugo, Next.js static export, etc.) — use Cloudflare Pages instead.
  • You want the lowest operational complexity.

The pageflare WASM module exposes a transform(html: string, config: object): string function. You wrap your Worker’s fetch handler so that HTML responses pass through transform before being returned to the client.

Client → Worker fetch handler → origin / cache
transform(html)
Optimized HTML → Client
Terminal window
npm install @pageflare/wasm
src/worker.ts
import { transform } from '@pageflare/wasm';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Pass non-HTML requests straight through
const response = await fetch(request);
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.includes('text/html')) {
return response;
}
const html = await response.text();
const optimized = transform(html, {
minify_html: true,
minify_css: true,
minify_js: true,
js_defer: true,
lazy_images: true,
img_dimensions: true,
font_swap: true,
});
return new Response(optimized, {
status: response.status,
headers: response.headers,
});
},
} satisfies ExportedHandler<Env>;
wrangler.toml
name = "pageflare-edge"
main = "src/worker.ts"
compatibility_date = "2024-01-01"
# WASM binding (if using a .wasm file directly rather than the npm package)
# [[wasm_modules]]
# name = "PAGEFLARE_WASM"
# path = "node_modules/@pageflare/wasm/pageflare_bg.wasm"

Pro optimizations require the license. Pass it via a Worker secret:

Terminal window
wrangler secret put PAGEFLARE_LICENSE

Then read it in your Worker:

const optimized = transform(html, {
license: env.PAGEFLARE_LICENSE,
minify_html: true,
// ...
});
Terminal window
wrangler deploy

Running WASM in a Worker adds latency to every HTML response. Keep the following in mind:

  • CPU time limits: Cloudflare Workers have CPU time limits (default 10 ms on the free plan, 30 ms on Paid). Complex optimization passes on large HTML pages may approach this limit. Benchmark with your actual pages before deploying to production.
  • Memory: WASM modules consume memory. The pageflare WASM module is approximately 2 MB. Workers are limited to 128 MB.
  • Cold starts: WASM instantiation adds to cold start time. Cloudflare mitigates this by keeping Workers warm, but the first request after a new deployment will be slower.
  • Caching strategy: Apply pageflare transformation before writing to the Cache API so the cached copy is already optimized:
const cache = caches.default;
const cacheKey = new Request(request.url, request);
let response = await cache.match(cacheKey);
if (!response) {
response = await fetch(request);
const html = await response.text();
const optimized = transform(html, config);
response = new Response(optimized, response);
// Cache the optimized version
await cache.put(cacheKey, response.clone());
}
return response;

You can apply different optimization levels based on request properties:

const isBot = /bot|crawler|spider/i.test(
request.headers.get('user-agent') ?? ''
);
const optimized = transform(html, {
minify_html: true,
// Only defer scripts for real users, not bots
js_defer: !isBot,
lazy_images: !isBot,
});
  • No filesystem access: The WASM runtime cannot self-host fonts or perform file-system reads. Features that require reading external files (e.g., self_host_fonts, critical_css inlining from disk) are not available.
  • No relative path resolution: Image dimension inference that requires reading image files from disk is not available; only HTML-embedded dimension hints work.
  • Experimental API: The WASM API surface may change between minor versions. Pin to a specific version in production.