Files
gh-jezweb-claude-skills-ski…/references/format-optimization.md
2025-11-30 08:24:18 +08:00

360 lines
7.2 KiB
Markdown

# Format Optimization
Complete guide to automatic WebP/AVIF conversion and format selection.
---
## format=auto (Recommended)
Automatically serve optimal format based on browser support.
**Priority**:
1. **AVIF** - Best compression (Chrome, Edge)
2. **WebP** - Good compression (Safari, Firefox)
3. **Original format** - Fallback (older browsers)
**Usage**:
```typescript
// URL format
/cdn-cgi/image/width=800,quality=85,format=auto/image.jpg
// Workers format
fetch(imageURL, {
cf: {
image: {
width: 800,
quality: 85,
format: 'auto'
}
}
});
// Cloudflare Images
https://imagedelivery.net/HASH/ID/w=800,q=85,f=auto
```
---
## Browser Support Detection
Cloudflare automatically checks the `Accept` header.
**Chrome/Edge**:
```
Accept: image/avif,image/webp,image/apng,image/*,*/*
```
→ Serves AVIF
**Safari**:
```
Accept: image/webp,image/apng,image/*,*/*
```
→ Serves WebP
**Older browsers**:
```
Accept: image/jpeg,image/png,image/*,*/*
```
→ Serves original format (JPEG)
---
## Manual Format Selection
### In URL Transformations
```html
<!-- AVIF (best compression) -->
<img src="/cdn-cgi/image/format=avif/image.jpg" />
<!-- WebP (good compression, wide support) -->
<img src="/cdn-cgi/image/format=webp/image.jpg" />
<!-- JPEG (progressive) -->
<img src="/cdn-cgi/image/format=jpeg/image.jpg" />
<!-- Baseline JPEG (older devices) -->
<img src="/cdn-cgi/image/format=baseline-jpeg/image.jpg" />
```
### In Workers
```typescript
// Get optimal format from Accept header
function getOptimalFormat(request: Request): 'avif' | 'webp' | 'auto' {
const accept = request.headers.get('accept') || '';
if (/image\/avif/.test(accept)) {
return 'avif';
} else if (/image\/webp/.test(accept)) {
return 'webp';
}
return 'auto'; // Cloudflare decides
}
return fetch(imageURL, {
cf: {
image: {
format: getOptimalFormat(request)
}
}
});
```
---
## Format Comparison
| Format | Compression | Quality | Support | Use Case |
|--------|-------------|---------|---------|----------|
| **AVIF** | Best (~50% smaller) | Excellent | Modern browsers | First choice (auto) |
| **WebP** | Good (~30% smaller) | Excellent | Wide support | Fallback from AVIF |
| **JPEG** | Standard | Good | Universal | Fallback, photos |
| **PNG** | Lossless | Lossless | Universal | Graphics, transparency |
**File Size Example** (1920x1080 photo):
- Original JPEG: 500 KB
- WebP: ~350 KB (30% smaller)
- AVIF: ~250 KB (50% smaller)
---
## Progressive vs Baseline JPEG
**Progressive JPEG** (default):
- Loads in multiple passes (low→high quality)
- Better for slow connections
- Slightly larger file size
**Baseline JPEG**:
- Loads top-to-bottom
- Better for older devices
- Slightly smaller file size
**Usage**:
```
format=jpeg → Progressive JPEG
format=baseline-jpeg → Baseline JPEG
```
---
## WebP Compression Modes
```typescript
// Fast compression (faster encoding, larger file)
fetch(imageURL, {
cf: {
image: {
format: 'webp',
compression: 'fast'
}
}
});
// Lossless WebP (no quality loss, larger file)
fetch(imageURL, {
cf: {
image: {
format: 'webp',
compression: 'lossless'
}
}
});
```
---
## Responsive Images with format=auto
```html
<picture>
<!-- Explicit AVIF for modern browsers -->
<source
type="image/avif"
srcset="
https://imagedelivery.net/HASH/ID/w=480,f=avif 480w,
https://imagedelivery.net/HASH/ID/w=1920,f=avif 1920w
"
/>
<!-- WebP fallback -->
<source
type="image/webp"
srcset="
https://imagedelivery.net/HASH/ID/w=480,f=webp 480w,
https://imagedelivery.net/HASH/ID/w=1920,f=webp 1920w
"
/>
<!-- JPEG fallback -->
<img
srcset="
https://imagedelivery.net/HASH/ID/w=480,f=jpeg 480w,
https://imagedelivery.net/HASH/ID/w=1920,f=jpeg 1920w
"
src="https://imagedelivery.net/HASH/ID/w=1920,f=jpeg"
alt="Responsive image with format fallbacks"
/>
</picture>
<!-- OR: Let format=auto handle it -->
<img
srcset="
https://imagedelivery.net/HASH/ID/w=480,f=auto 480w,
https://imagedelivery.net/HASH/ID/w=1920,f=auto 1920w
"
src="https://imagedelivery.net/HASH/ID/w=1920,f=auto"
alt="Auto-format responsive image"
/>
```
---
## Quality Recommendations by Format
```typescript
const qualitySettings = {
jpeg: 85, // Standard for photos
webp: 85, // Same as JPEG
avif: 85, // AVIF efficient at same quality
png: undefined, // Lossless (quality N/A)
graphics: 95 // High quality for logos/text
};
// Photos
/cdn-cgi/image/width=800,quality=85,format=auto/photo.jpg
// Graphics with text
/cdn-cgi/image/width=800,quality=95,format=auto/logo.png
// Thumbnails (lower quality acceptable)
/cdn-cgi/image/width=300,quality=75,format=auto/thumb.jpg
```
---
## Animation Support
**GIF**:
```
format=auto → Still GIF or first frame
anim=true → Preserve animation
```
**Animated WebP**:
```typescript
fetch(animatedGif, {
cf: {
image: {
format: 'webp',
anim: true // Preserve animation
}
}
});
```
---
## Metadata Handling
**Strip metadata** (smaller file size):
```
metadata=none
```
**Keep copyright** (default for JPEG):
```
metadata=copyright
```
**Keep all EXIF** (GPS, camera settings):
```
metadata=keep
```
**Example**:
```
/cdn-cgi/image/width=800,format=auto,metadata=none/photo.jpg
```
---
## Cost Optimization
1. **Use format=auto**: Smallest files = less bandwidth
2. **Reasonable quality**: 80-85 for photos, 90-95 for graphics
3. **Strip metadata**: `metadata=none` for public images
4. **Cache at edge**: First transformation billable, subsequent free
5. **WebP animations**: Convert GIF to animated WebP (smaller)
---
## Testing Format Support
```html
<script>
// Check AVIF support
const avifSupport = document.createElement('canvas')
.toDataURL('image/avif').indexOf('data:image/avif') === 0;
// Check WebP support
const webpSupport = document.createElement('canvas')
.toDataURL('image/webp').indexOf('data:image/webp') === 0;
console.log('AVIF:', avifSupport); // true in Chrome/Edge
console.log('WebP:', webpSupport); // true in modern browsers
</script>
```
**But**: Let Cloudflare handle this with `format=auto`!
---
## Common Patterns
### Hero Image
```
width=1920,height=1080,fit=cover,quality=85,format=auto,metadata=none
```
### Thumbnail
```
width=300,height=300,fit=cover,quality=75,format=auto,metadata=none
```
### Avatar
```
width=200,height=200,fit=cover,gravity=face,quality=90,format=auto
```
### Product Photo
```
width=800,height=800,fit=contain,quality=90,sharpen=2,format=auto
```
### Blur Placeholder (LQIP)
```
width=50,quality=10,blur=20,format=webp,metadata=none
```
---
## Best Practices
1. **Always use format=auto**: Let Cloudflare optimize
2. **Quality 80-90**: Balance file size and quality
3. **Strip unnecessary metadata**: Smaller files
4. **Test on real devices**: Verify format delivery
5. **Monitor bandwidth**: Check Cloudflare Analytics
6. **Use WebP for animations**: Smaller than GIF
7. **Progressive JPEG for photos**: Better perceived load time
---
## Official Documentation
- **Transform via URL**: https://developers.cloudflare.com/images/transform-images/transform-via-url/
- **Supported Formats**: https://developers.cloudflare.com/images/transform-images/#supported-formats-and-limitations