@clementvial

Developer from Canada 🇨🇦
Product, infrastructure, AI, and web3.
Mostly on AWS and Cloudflare.

All notes

Astro Prerenders in workerd Now, and sharp Does Not Run There

Upgrading this site’s Astro version broke the build on a page that hadn’t changed in months. The adapter used to prerender static pages in Node. It now does it inside workerd by default, so build time matches production as closely as possible.

Reasonable, and it means anything Node-only that runs during prerendering stops working. In my case that was sharp, a native binary with no chance of loading in workerd.

There’s a switch for it:

astro.config.mjs
adapter: cloudflare({
imageService: 'compile',
prerenderEnvironment: 'node',
}),

On-demand pages are unaffected and always run in workerd. This only changes where the build-time render happens.

Then check your images

The build went green and my images came out wrong, with no warning of any kind.

imageService: 'compile' is supposed to run sharp at build time and emit optimized files. Combined with prerenderEnvironment: 'node', it took a path where the image service was never installed, so every generated file was a byte-for-byte copy of the source with the new extension stapled on. PNG bytes in a file called .webp.

The check takes a few seconds:

ls -l dist/_astro/*.webp

If a .webp weighs exactly what the source PNG weighed, nothing was transformed. A real conversion is usually a fraction of the original.

Worth the two settings

Both options are one line, and the combination is common enough that the adapter has since grown a fix for it. Still worth verifying after any adapter upgrade, because the failure mode is silence rather than an error.

The wider lesson from this upgrade: a build that runs in the production runtime catches real incompatibilities, but it also means the build now has all of the runtime’s restrictions. Those two things arrive together.