6mb
6mb

Optimizing image again

By Jeff Byer

Updated todo list

I'll add client-side resize + WebP recompression in media.ts so it runs before upload — no extra Worker cost, works for both the Media page upload and the MarkdownField drag/paste/upload flow.

Read

Read

Replacing 22 lines with 109 lines in


The Media admin page bypasses uploadMedia with a raw fetch. Let me route it through the same helper.

Replacing 34 lines with 29 lines in


Checked , , no problems found

Created 2 todos

Ran terminal command: npm run check 2>&1 | tail -5 && npm run build 2>&1 | tail -5 && npx wrangler deploy 2>&1 | tail -5

Deployed (version f58add9a).

What happens on upload now (media.ts):

  1. Image is decoded in the browser via createImageBitmap(file).
  2. If the longest edge exceeds 2000px, it's downscaled proportionally.
  3. Re-encoded to WebP at quality 0.85 using OffscreenCanvas.convertToBlob() (with an HTMLCanvasElement.toBlob fallback for older browsers).
  4. Uploaded with a .webp filename.

Safe-fallback cases that skip processing (original file uploaded unchanged):

  • Non-image MIME types.
  • image/svg+xml (would rasterize a vector — bad).
  • image/gif (would lose animation).
  • Browser can't decode (e.g. HEIC on non-Safari) — createImageBitmap throws → original passes through.
  • Image is already under the cap and already WebP — no work to do.
  • Re-encoded result would be larger than the original (rare with pre-compressed input).

Coverage: every upload path now uses this:

  • Drag/paste/Insert-image inside the MarkdownField (was already calling uploadMedia).
  • MediaImageField for post cover / OG / person photo (was already calling uploadMedia).
  • The Media library's upload button (previously did a raw fetch; now routed through uploadMedia).

Tuning knobs: uploadMedia(file, { maxDimension, quality }) accepts overrides if you want, e.g., a tighter cap for inline body images vs. cover images. The server side (api/media/upload) already allows image/webp and enforces a 10 MB ceiling as a final guard.

Want me to drop a tighter cap (say 1200px) on inline body-image uploads from the MarkdownField, while keeping 2000px for cover images?

Made changes.