/about/ transfers 34MB, mostly unresized phone photos #129

Open
opened 2026-08-25 08:50:46 +00:00 by coilyco-ops · 0 comments
Collaborator

Found by the page-weight budget added alongside #126, on its first run. Measured as real transfer via the Performance API in Cypress, not as file sizes on disk.

The measurement

/about/                          35,111 K
/                                   709 K
/posts/3-cloud-standoff/             92 K
... every other route             62-92 K

/about/ is roughly fifty times the next heaviest route and four hundred times a typical post.

What it is

8,023 K  /my-life/project-galaxy-gen.gif           960x540
7,469 K  /my-life/14-two-monitor-desktop.jpg       4032x3024
6,634 K  /my-life/18-garden-bed-construction.jpg   3024x4032
4,049 K  /my-life/12-wall-under-construction.jpg   3024x4032
2,093 K  /my-life/08-motherboard-and-gpu.jpg       3072x4080
2,023 K  /my-life/16-car-headphones-sunglasses.jpg 2736x3648
  721 K  /my-life/project-factory-game.gif
  636 K  /my-life/05-eco-app-dashboard.png

Those are straight-off-the-phone 12 megapixel originals, displayed at a fraction of their pixel size. That is waste rather than a quality decision, and resizing to display scale is not a visual call.

The GIF is different. 8MB for 960x540 is what GIF costs for video-like content, and the fix there is a real change rather than a resize.

Three separable pieces

1. No intrinsic dimensions. Not one of the 33 images on the page carries width or height. Two consequences:

  • Lazy loading does not work. I added loading="lazy" to 32 of the 33 and the measured transfer did not move. Without reserved space every image collapses to zero height, so the whole page sits inside the browser's lazy threshold and everything loads anyway. Confirmed by measuring before and after rather than by reading the attribute.
  • Cumulative layout shift, for the same reason.

This is the cheapest fix and it is what unlocks the second one.

2. Resize the photos. Long edge down to display scale. On the five photos above that is roughly 21MB recovered with no visible change at the size they render.

3. The GIF. project-galaxy-gen.gif at 8MB is the single largest asset on the site. Converting to MP4 or WebM inside a <video> typically costs a few hundred KB, but it changes the element and its behaviour, so it wants a deliberate decision rather than a silent swap.

Why it went unnoticed

Nothing measured it. The suite asserted no render-blocking script and no third-party origin, both of which pass, and neither has anything to say about 34MB of first-party images.

The budget now in cypress/e2e/weight.cy.ts carries /about/ at 36000K, which is a record of the defect rather than a budget. Ratchet it down as this lands, and delete the entry when it reaches the 150K default.

Done means

  • Every image on /about/ carries width and height
  • loading="lazy" verifiably defers, confirmed by the measured transfer dropping rather than by the attribute being present
  • Photos resized to display scale
  • A decision recorded on the galaxy-gen GIF, either converted or deliberately kept
  • /about/'s entry in BUDGETS lowered to match, or removed
Found by the page-weight budget added alongside `#126`, on its first run. Measured as real transfer via the Performance API in Cypress, not as file sizes on disk. ## The measurement ``` /about/ 35,111 K / 709 K /posts/3-cloud-standoff/ 92 K ... every other route 62-92 K ``` `/about/` is roughly **fifty times** the next heaviest route and **four hundred times** a typical post. ## What it is ``` 8,023 K /my-life/project-galaxy-gen.gif 960x540 7,469 K /my-life/14-two-monitor-desktop.jpg 4032x3024 6,634 K /my-life/18-garden-bed-construction.jpg 3024x4032 4,049 K /my-life/12-wall-under-construction.jpg 3024x4032 2,093 K /my-life/08-motherboard-and-gpu.jpg 3072x4080 2,023 K /my-life/16-car-headphones-sunglasses.jpg 2736x3648 721 K /my-life/project-factory-game.gif 636 K /my-life/05-eco-app-dashboard.png ``` Those are **straight-off-the-phone 12 megapixel originals**, displayed at a fraction of their pixel size. That is waste rather than a quality decision, and resizing to display scale is not a visual call. The GIF is different. 8MB for 960x540 is what GIF costs for video-like content, and the fix there is a real change rather than a resize. ## Three separable pieces **1. No intrinsic dimensions.** Not one of the 33 images on the page carries `width` or `height`. Two consequences: * **Lazy loading does not work.** I added `loading="lazy"` to 32 of the 33 and the measured transfer did not move. Without reserved space every image collapses to zero height, so the whole page sits inside the browser's lazy threshold and everything loads anyway. Confirmed by measuring before and after rather than by reading the attribute. * Cumulative layout shift, for the same reason. This is the cheapest fix and it is what unlocks the second one. **2. Resize the photos.** Long edge down to display scale. On the five photos above that is roughly 21MB recovered with no visible change at the size they render. **3. The GIF.** `project-galaxy-gen.gif` at 8MB is the single largest asset on the site. Converting to MP4 or WebM inside a `<video>` typically costs a few hundred KB, but it changes the element and its behaviour, so it wants a deliberate decision rather than a silent swap. ## Why it went unnoticed Nothing measured it. The suite asserted no render-blocking script and no third-party origin, both of which pass, and neither has anything to say about 34MB of first-party images. The budget now in `cypress/e2e/weight.cy.ts` carries `/about/` at 36000K, which is a record of the defect rather than a budget. **Ratchet it down as this lands, and delete the entry when it reaches the 150K default.** ## Done means - [ ] Every image on `/about/` carries `width` and `height` - [ ] `loading="lazy"` verifiably defers, confirmed by the measured transfer dropping rather than by the attribute being present - [ ] Photos resized to display scale - [ ] A decision recorded on the galaxy-gen GIF, either converted or deliberately kept - [ ] `/about/`'s entry in `BUDGETS` lowered to match, or removed
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilysiren/website#129
No description provided.