Skip to content

Halve the weight of assets/images and keep it that way - #108

Open
ultimatecoder wants to merge 1 commit into
masterfrom
fix/optimize-image-weight
Open

Halve the weight of assets/images and keep it that way#108
ultimatecoder wants to merge 1 commit into
masterfrom
fix/optimize-image-weight

Conversation

@ultimatecoder

Copy link
Copy Markdown
Owner

What #31 asked for

At present, an author has to manually minify images before uploading/linking them with the post. It will save a lot of work if this process is automated.

So the deliverable is the automation, with the one-time cleanup as its first run.

scripts/optimize-images rewrites oversized images in place; --check reports them and changes nothing. scripts/test runs --check before building, so CI fails a PR that adds an oversized image rather than letting it ship.

Budget Photos (jpg/png) Screencasts (gif)
Max file size 300 KB 1.2 MB
Max dimension 1600px long edge 1200px wide

Files already within budget are skipped, so the script is idempotent — verified by running it twice, the second run rewrote nothing. That matters: re-encoding an already-fine JPEG would lose quality for no gain.

Result

assets/images:  25 MB -> 10 MB

  photos       17.5 MB -> 7.4 MB   (58%)
  screencasts   7.1 MB -> 2.8 MB   (61%)

Largest single file is now 256 KB (was 2.2 MB).

This also closes #32

#32 proposed generating a second, smaller copy of every image for feed readers, since RSS applies no CSS and renders images at native size. That was the right diagnosis of a real problem — but the cause was 3328px photos, not the lack of a second variant.

With the cap in place the largest photo any reader receives is 256 KB. A separate RSS variant would mean a build step and a second set of files to maintain, for no practical gain. Closing it as resolved by the cap rather than by the originally proposed mechanism.

Two findings that shaped the pipeline

sips resizes well but encodes badly. On a 2048px photo it produced 452 KB where cjpeg produced 262 KB from identical pixels. Across all 42 photos that is the difference between 25% and 58% saved. My first three spot-checks looked great only because they were extreme-dimension outliers — the typical 2048px photo barely shrank. So sips only resizes; cjpeg encodes at quality 80, optimized and progressive.

For screencasts only dimensions matter. On the largest GIF:

Setting Result
-O3 lossless 2.60 MB → 2.47 MB
--colors 64 2.33 MB
--lossy=60 2.41 MB
--resize-fit-width 1200 1.05 MB

Palette and lossy tricks save under 7% because the size is 1320 frames of pixel data, not palette. These are 1920px recordings displayed in an 800px column, so 1200px leaves headroom and the terminal text stays legible.

Verification

  • ./scripts/test passes (image check + build + htmlproofer, 173 external / 72 internal links)
  • Lighthouse SEO suite still passes on all 7 audited pages
  • --check exits 0; running the optimizer a second time is a no-op
  • Spot-checked a re-encoded group photo and an extracted screencast frame — photo visually identical, GIF animation intact at 1200×675

Closes #31
Closes #32

🤖 Generated with Claude Code

Issue #31 asks for image minification to stop being a manual step before
every post. `scripts/optimize-images` is that step: run bare it rewrites
oversized images in place, and `--check` reports them without touching
anything. `scripts/test` now runs `--check` first, so CI fails a pull
request that adds an image over budget instead of letting it ship.

The budgets are 300 KB for photos, capped at 1600px on the long edge, and
1.2 MB for animated GIFs, capped at 1200px wide. Files already inside their
budget are skipped, which keeps the script idempotent — re-encoding a JPEG
that is already fine would lose quality for nothing.

Running it over the existing images takes assets/images from 25 MB to
10 MB. Photos went from 17.5 MB to 7.4 MB and the screencasts from 7.1 MB
to 2.8 MB. This also answers #32, which asked for a second smaller copy of
each image for feed readers: the largest photo any reader now receives is
256 KB, so a separate RSS variant would add a build step and a second set
of files to maintain for no practical gain.

Two findings shaped the pipeline.

sips resizes correctly but writes bulky JPEGs. On a 2048px photo it
produced 452 KB where cjpeg produced 262 KB from the identical pixels —
25% off the total versus 58%. So sips only resizes and cjpeg encodes, at
quality 80, optimized and progressive.

For the screencasts, only dimensions matter. On the largest one, palette
reduction and lossy LZW each saved under 7%, while halving the width saved
60%. They are 1920px recordings shown in an 800px column, so 1200px still
leaves headroom and the terminal text stays legible.

Closes #31
Closes #32

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ultimatecoder

Copy link
Copy Markdown
Owner Author

Github runners are having issue, thus SEO audit job has failed and on-re-run waiting to be picked up. Reference: https://www.githubstatus.com/incidents/qcvjkzcs7j74

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Images with RSS is too large Solution for minifying uploaded image automatically

1 participant