Roll out client-side image compression to market + profile #59
Labels
No labels
app:activities
app:chat
app:events
app:forum
app:libra
app:market
app:restaurant
app:tasks
app:wallet
app:webapp
bug
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aiolabs/webapp#59
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Background
ImageUploadServicenow supports client-side resize + re-encode before the pict-rs POST, gated behind an opt-incompressoption /<ImageUpload :compress="true">prop. Events adopted it for banner uploads in commit [TODO: link once pushed].Defaults when enabled (in
src/modules/base/services/ImageUploadService.ts):maxWidthOrHeight: 1920maxSizeMB: 1(target output, not validation cap)fileType: 'image/webp'initialQuality: 0.85useWebWorker: trueEXIF orientation is handled by
browser-image-compression; WebP encoding falls back to original-on-failure.Gap
The existing consumers still upload originals untouched:
src/modules/market/components/CreateProductDialog.vue— up to 5 images per product, each potentially a 5–8 MB phone photo. The hot path on a busy marketplace.src/modules/base/components/ProfileSettings.vue— profile avatar.Pict-rs at img.ariege.io stores every original at full resolution forever;
process.webp?resize=…URLs only affect delivery. So the disk hit is real.Proposal
Two options, pick one:
ImageUploadServicesocompressdefaults totrueand consumers opt out if they have a reason. Minimal surface — one-line change in the service; no consumer churn.:compress="true"(or tuned options) to each<ImageUpload>site. More explicit at the call site, slightly more code.Suggested split for option 2:
:compress="true"with default knobs (banner-like, posters and product shots in the same size class).:compress="{ maxWidthOrHeight: 512, maxSizeMB: 0.2 }"— avatars don't need 1920 px.I lean (1) since it shrinks the trap surface — a future consumer that forgets the prop still gets compressed uploads.
Out of scope
Sources
Reasoning + format choice (WebP over AVIF, resize-first-then-quality, EXIF orientation footgun) — see the events PR description / commit body.
Both consumers rolled out — went with option 2 (per-consumer opt-in) since profile wants different knobs than market:
c1194dafeat(market): client-side compress product image uploads — default knobs (1920px / WebP / q=0.85), matches the events banner casea815442feat(base/profile): compress avatar uploads with tight 512px cap —{ maxWidthOrHeight: 512, maxSizeMB: 0.2 }since avatars don't need 1920pxcompressstays opt-in in the service. Default-on is still on the table for a future change once we're confident no consumer wants raw originals.