3.8 KiB
3.8 KiB
Spec: Image Processing Refactor
Context
Current image handling uses on-demand resize via /uploads-resized/ route. Admin uploads save originals as-is (jpg/png/webp), and resize happens on first request. User uploads (reviews, 2MB limit) also use on-demand resize.
Goals
- User images (reviews, ≤2MB): Improve size error messages to be user-friendly
- Admin images (products, ≤20MB): Eager processing at upload time
- Generate all resize widths (320, 640, 1024, 1600) in AVIF + WebP
- Convert original to WebP (delete source file)
- Full-screen viewer shows original in WebP (no width limit)
- Thumbnails use resized versions from cache
Architecture
Server Changes
1. server/src/lib/upload-images.js
- Add
eagerparameter topersistMultipartImages - When
eager: true, after saving each file:- Call
generateAllSizes(uuid, subdir, fullPath)— generates all sizes from original - Call
convertOriginalToWebp(uuid, subdir)— converts original to WebP, deletes source - Update URL to use
.webpextension (replace original extension)
- Call
2. server/src/lib/image-resize.js
- Add
generateAllSizes(uuid, subdir, originalPath):- For each width in [320, 640, 1024, 1600]:
- Generate AVIF and WebP in
.cache/<subdir>/
- Generate AVIF and WebP in
- Uses original file path (before conversion to WebP)
- For each width in [320, 640, 1024, 1600]:
- Add
convertOriginalToWebp(uuid, subdir):- Find original file (jpg/png)
- Convert to WebP (quality 80) at same location with
.webpextension - Delete original jpg/png file
- Return new
.webppath
3. server/src/routes/api/admin-products.js
- Pass
eager: truetopersistMultipartImages
4. server/src/routes/api/public-reviews.js
- Improve error message for file too large (413)
Client Changes
1. client/src/entities/product/api/product-api.ts
- Add pre-upload size check for review images
- Clear error message: "Файл «» слишком большой (максимум 2 МБ)"
2. client/src/shared/ui/OptimizedImage.tsx
- Update
buildSrcSetto use cached AVIF/WebP directly - Full-screen viewer: use original
.webpURL (no?w=) - Remove fallback to original format for upload URLs
3. client/src/features/product-review/ui/ReviewDialog.tsx
- Show user-friendly error message for oversized files
Data Flow
Admin Upload (Eager)
- Client sends FormData to
POST /api/admin/uploads - Server saves original (e.g.,
uuid.jpg) - Server generates all sizes in
.cache/from original - Server converts original to WebP (
uuid.webp), deletesuuid.jpg - Returns URLs with
.webpextension (e.g.,/uploads/<uuid>.webp) - Client displays using OptimizedImage with srcset from cache
User Upload (Reviews)
- Client validates file size ≤2MB before upload
- Server validates and saves original
- On-demand resize still works (existing flow)
- Clear error messages at both client and server
Error Handling
User Upload Size Error
- Client: Pre-upload check with message "Файл «» слишком большой (максимум 2 МБ)"
- Server: 413 with "Файл слишком большой (максимум 2 МБ)"
Admin Upload Processing Error
- If sharp fails: return 500 with "Ошибка обработки изображения"
- If file not found after save: return 500 with "Внутренняя ошибка сервера"
Testing
Server Tests
- Test
generateAllSizescreates all width+format combinations - Test
convertOriginalToWebpconverts and deletes original - Test
persistMultipartImageswitheager: true - Test error messages for oversized files
Client Tests
- Test pre-upload size validation for reviews
- Test OptimizedImage srcset generation for WebP originals
- Test error message display in ReviewDialog