Optimizes images for web performance by converting to modern formats, compressing, and generating responsive sizes.
Optimizes images for web performance using modern formats and compression techniques.
First, scan for images in the project:
# Find all images
find . -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" \)
Present findings:
Verify available tools:
# Check for ImageMagick
which convert || echo "ImageMagick not found"
# Check for cwebp (WebP encoder)
which cwebp || echo "cwebp not found"
# Check for sharp-cli (if Node.js project)
which sharp || echo "sharp not found"
If tools missing, provide installation instructions:
# macOS
brew install imagemagick webp
# Ubuntu/Debian
apt-get install imagemagick webp
# Node.js projects (recommended)
npm install -g sharp-cli
Present optimization strategy:
For WebP Conversion:
# Convert JPG/PNG to WebP with 80% quality
cwebp -q 80 input.jpg -o input.webp
For PNG Optimization:
# Compress PNG without quality loss
convert input.png -strip -quality 85 output.png
For JPEG Optimization:
# Optimize JPEG with progressive loading
convert input.jpg -strip -interlace Plane -quality 85 output.jpg
For Responsive Sizes:
# Generate multiple sizes (sharp-cli)
sharp -i input.jpg -o output-{width}.jpg resize 320 480 768 1024 1920
Present plan with:
Wait for explicit confirmation before proceeding.
Create organized output structure:
# Backup originals
mkdir -p images/original
cp images/*.{jpg,png} images/original/
# Create optimized versions
mkdir -p images/optimized
Process each image with progress updates.
For HTML projects, offer to generate <picture> elements:
<picture>
<source
srcset="image-320.webp 320w,
image-768.webp 768w,
image-1920.webp 1920w"
type="image/webp"
/>
<source
srcset="image-320.jpg 320w,
image-768.jpg 768w,
image-1920.jpg 1920w"
type="image/jpeg"
/>
<img
src="image-768.jpg"
alt="Description"
loading="lazy"
width="768"
height="432"
/>
</picture>
For Next.js projects, suggest image configuration:
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}
For Gatsby projects, suggest gatsby-plugin-image setup.
For vanilla projects, suggest lazy loading:
// Lazy load images
if ('loading' in HTMLImageElement.prototype) {
// Browser supports native lazy loading
document.querySelectorAll('img[loading="lazy"]').forEach(img => {
img.src = img.dataset.src;
});
} else {
// Use IntersectionObserver polyfill
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
imageObserver.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
}
Show final metrics:
Recommend:
JPEG:
PNG:
WebP:
Use WebP when:
Use AVIF when:
Keep JPEG/PNG when:
<picture> elementCommon breakpoints:
Target sizes:
# Create backup before optimization
mkdir -p backups/$(date +%Y%m%d)
cp -r images/ backups/$(date +%Y%m%d)/
# Check if conversion succeeded
if [ $? -eq 0 ]; then
echo "✅ Optimized successfully"
else
echo "❌ Optimization failed, keeping original"
fi
Offer to create optimization script:
#!/bin/bash
# optimize-images.sh
set -e
INPUT_DIR=${1:-.}
OUTPUT_DIR="optimized"
QUALITY=80
mkdir -p "$OUTPUT_DIR"
echo "🖼️ Optimizing images in $INPUT_DIR..."
# Process JPEGs
for img in "$INPUT_DIR"/*.{jpg,jpeg,JPG,JPEG}; do
[ -f "$img" ] || continue
filename=$(basename "$img" | sed 's/\.[^.]*$//')
# Original format
convert "$img" -strip -interlace Plane -quality $QUALITY \
"$OUTPUT_DIR/${filename}.jpg"
# WebP format
cwebp -q $QUALITY "$img" -o "$OUTPUT_DIR/${filename}.webp"
echo "✅ $filename"
done
# Process PNGs
for img in "$INPUT_DIR"/*.{png,PNG}; do
[ -f "$img" ] || continue
filename=$(basename "$img" | sed 's/\.[^.]*$//')
# Optimize PNG
convert "$img" -strip -quality 85 "$OUTPUT_DIR/${filename}.png"
# WebP with alpha
cwebp -q $QUALITY -lossless "$img" -o "$OUTPUT_DIR/${filename}.webp"
echo "✅ $filename"
done
echo "🎉 Optimization complete!"
echo "📊 Space saved:"
du -sh "$INPUT_DIR"
du -sh "$OUTPUT_DIR"
Suggest adding to .gitignore:
# Original unoptimized images
images/original/
*-original.jpg
*-original.png
# Large image files
*.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
Or suggest Git LFS for large images:
# Install Git LFS
git lfs install
# Track large images
git lfs track "*.jpg"
git lfs track "*.png"
# Add to repo
git add .gitattributes
For automated optimization in build pipeline:
GitHub Actions:
name: Optimize Images
on:
pull_request:
paths:
- 'images/**'
jobs:
optimize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install tools
run: |
sudo apt-get install -y imagemagick webp
- name: Optimize images
run: |
chmod +x scripts/optimize-images.sh
./scripts/optimize-images.sh images
- name: Commit optimized images
run: |
git config --local user.name "Image Optimizer Bot"
git add images/optimized
git commit -m "chore: optimize images"
git push
Optimized images improve:
Before optimization:
After optimization:
On 3G connection:
❌ Over-optimization: Quality too low (< 70) ❌ Under-optimization: Quality too high (> 95) ❌ No fallbacks: Only serving WebP without JPEG/PNG ❌ Wrong format: Using PNG for photos ❌ Missing dimensions: Causing layout shift ❌ No lazy loading: Loading all images immediately ❌ Single size: Not using responsive images
import Image from 'next/image'
<Image
src="/images/hero.jpg"
alt="Hero image"
width={1920}
height={1080}
priority // For LCP images
placeholder="blur"
/>
import { StaticImage } from "gatsby-plugin-image"
<StaticImage
src="../images/hero.jpg"
alt="Hero image"
placeholder="blurred"
layout="fullWidth"
/>
<nuxt-img
src="/images/hero.jpg"
alt="Hero image"
width="1920"
height="1080"
format="webp"
loading="lazy"
/>