notes
Sep 5, 2024 · 1 min read

Letting Astro Own My Images

For the first few months of this rebuild I had a small Node script that ran before every build: read every image in src/assets, resize it to three widths, write out .webp copies, and hope I remembered to run it before pushing. It worked, in the sense that it never crashed. It also meant every image import was a leap of faith that the resized file actually existed.

The thing I was avoiding

Astro’s built-in <Image /> component does exactly what my script did, except it runs as part of the build itself, which means a missing or oversized image is a build failure instead of a shipped bug. I’d avoided switching for months because “my script already works” felt like a good enough reason not to touch it.

---
import { Image } from 'astro:assets';
import cover from '../assets/cover.jpg';
---
<Image src={cover} width={800} alt="Post cover" />

Swapping it in took about forty minutes, most of which was deleting the old script and its two npm dependencies. The build got slightly slower — Astro does more work per image than my script did — but the deploy got faster, because Cloudflare Pages was now serving pre-optimized .webp output at the exact widths each template actually requests, instead of the three fixed sizes I’d guessed at eight months earlier.

What I actually learned

The lesson wasn’t about image formats. It was that “it already works” is doing a lot of unpaid labor as a reason not to adopt something. My script worked. It also had no error handling, no responsive srcset, and lived entirely in my head. The framework’s version does more, does it more correctly, and I don’t have to remember to run it.