Skip to content

Imagini: 215 MB → 77 MB, WebP servit prin <picture>, lazy-loading corectat

Vitalie requested to merge 7_image-weight into main

Închide #7 (closed) pe partea de fișiere și de livrare. Cele patru puncte din issue, în ordine.

Ce s-a schimbat

Unealtă nouă: tools/image-optimizer. Rulează la cerere peste frontend/public, nu la fiecare build — sharp stă în propriul package.json, deci nici pipeline-ul, nici imaginea de frontend nu-l instalează. npm run check verifică invariantul.

Conversia. 214,8 MB de rastere au devenit 47,5 MB de rastere + 29,2 MB de WebP. Latura lungă e plafonată la 1600 px (nimic pe site nu se afișează peste 960 px CSS, măsurat la 1920 și la 430). 147 de fișiere .png care nu aveau nicio transparență reală au devenit .jpg; cele 164 cu transparență adevărată au rămas .png. Fiecare raster are acum un frate .webp mai mic decât el.

Livrarea. frontend/src/components/Picture.tsx randează <picture> cu sursa WebP înaintea rasterului. Se aplică doar căilor locale: o imagine încărcată din panou, un URL absolut sau un SVG rămân exact ce erau, pentru că <picture> nu are a doua șansă — o sursă acceptată și negăsită înseamnă imagine ruptă, nu una mai lentă.

Lazy-loading. loading="lazy" era pus pe două imagini vizibile fără scroll (hero-ul de colecție și cardul cadou) și lipsea de pe șaptesprezece care nu sunt. Ambele sensuri corectate.

Bază de date. backend/prisma/rename-image-extensions.ts duce redenumirea în bazele deja populate: seed.ts face upsert(..., update: {}) pe produse, deci un hoverImage stocat ar rămâne pentru totdeauna pe un fișier care nu mai există. Rescrie doar potriviri exacte din tabelul de 147, deci un upload făcut între timp de admin supraviețuiește. Idempotent.

Verificare

  • npx tsc -p tsconfig.app.json --noEmit curat, oxlint cu singurul avertisment preexistent (src/App.tsx:69), 181 de teste frontend, 417 teste backend, ambele build-uri trec.
  • find frontend/public -size +1000k → 0. -size +300k → 0.
  • Test nou, publicAssets.test.ts: fiecare cale de imagine scrisă în cod are fișier pe disc, fiecare raster are frate .webp, nimic peste 300 KB. Nimic altceva din proiect nu observa o cale ruptă.
  • Randat local la 1920 și 430 pe 13 pagini: 816 imagini comparate cu producția, 0 diferențe de geometrie, 0 imagini rupte, 0 răspunsuri 4xx.
  • Scriptul de redenumire rulat pe o copie a bazei: 63 de valori în 63 de rânduri (Product 32, ProductDetail 29, ContentListItem 2), a doua rulare nu mai găsește nimic, iar după el nicio cale din bază nu mai lipsește de pe disc.

Ordinea de livrare — obligatorie

  1. Merge → deploy (imaginile noi ajung pe disc).
  2. Abia apoi rename-image-extensions.ts pe bază. Invers, baza ar spune .jpg în timp ce containerul are încă .png, și pozele produselor ar dispărea.

Înscrierea scriptului în cele două joburi manuale vine într-un MR separat: orice diff care atinge .gitlab-ci.yml lasă MR-ul fără pipeline, deci fără build și fără deploy.

Rămâne în afara acestui MR

  • Punctul patru din issue, Cloudflare Polish, nu se mai justifică: era o măsură de avarie până intra conversia, iar acum ar recomprima fișiere deja optimizate.
  • Imaginile încărcate din panou nu trec prin nimic — backend/src/lib/uploads.ts le scrie așa cum vin. Hero-ul paginii principale, elementul LCP, e chiar un astfel de fișier. Primește issue propriu.

Merge request reports