Server-side image optimization
Server optimization converts uploaded images to modern formats (WebP, AVIF), picks optimal quality and size, reduces data transfer by 40–70%.
Node.js: Sharp pipeline
import sharp from 'sharp';
interface OptimizeOptions {
maxWidth?: number;
quality?: number;
format?: 'webp' | 'avif' | 'jpeg';
}
async function optimizeImage(inputBuffer: Buffer, options: OptimizeOptions = {}): Promise<Buffer> {
const { maxWidth = 1920, quality = 80, format = 'webp' } = options;
return sharp(inputBuffer)
.resize(maxWidth, undefined, {
withoutEnlargement: true,
fit: 'inside',
})
.toFormat(format, {
quality,
effort: 4, // speed/size balance
})
.withMetadata({ orientation: undefined }) // remove EXIF rotation
.toBuffer();
}
// Middleware for lazy optimization
app.get('/images/:key', async (req, res) => {
const { key } = req.params;
const { w, q = '80', f = 'webp' } = req.query;
// Check cache
const cacheKey = `${key}:${w}:${q}:${f}`;
const cached = await s3.getObject({ Key: `optimized/${cacheKey}.${f}` }).catch(() => null);
if (cached) {
return res.type(`image/${f}`).send(await streamToBuffer(cached.Body));
}
// Get original
const original = await s3.getObject({ Key: `originals/${key}` });
const buffer = await streamToBuffer(original.Body);
// Optimize
const optimized = await optimizeImage(buffer, {
maxWidth: w ? parseInt(w as string) : 1920,
quality: parseInt(q as string),
format: f as 'webp' | 'avif' | 'jpeg',
});
// Cache
await s3.putObject({
Key: `optimized/${cacheKey}.${f}`,
Body: optimized,
ContentType: `image/${f}`,
CacheControl: 'public, max-age=31536000',
});
res.type(`image/${f}`).send(optimized);
});
PHP: optimization on upload
use Intervention\Image\Facades\Image;
class ImageOptimizationService
{
const FORMATS = ['webp', 'avif'];
const SIZES = [400, 800, 1200, 1920];
public function process(UploadedFile $file): array
{
$image = Image::make($file->getPathname());
// Remove EXIF and rotate by orientation
$image->orientate()->stripExif();
$paths = [];
foreach (self::SIZES as $width) {
if ($image->width() < $width) continue;
$resized = clone $image;
$resized->resize($width, null, fn($c) => $c->aspectRatio()->upsize(false));
foreach (self::FORMATS as $format) {
$quality = $format === 'avif' ? 60 : 82;
$key = "images/{$width}w/{$this->generateKey()}.{$format}";
Storage::disk('s3')->put(
$key,
$resized->encode($format, $quality)->__toString(),
['CacheControl' => 'public, max-age=31536000']
);
$paths[$format][$width] = $key;
}
}
return $paths;
}
}
HTML: responsive images with srcset
// Blade helper for optimized images
function responsive_img(array $paths, string $alt, string $sizes = '100vw'): string
{
$avifSrcset = collect($paths['avif'] ?? [])->map(fn($path, $width) =>
Storage::disk('s3')->url($path) . " {$width}w"
)->join(', ');
$webpSrcset = collect($paths['webp'] ?? [])->map(fn($path, $width) =>
Storage::disk('s3')->url($path) . " {$width}w"
)->join(', ');
$fallback = Storage::disk('s3')->url(end($paths['webp']));
return <<<HTML
<picture>
<source type="image/avif" srcset="{$avifSrcset}" sizes="{$sizes}">
<source type="image/webp" srcset="{$webpSrcset}" sizes="{$sizes}">
<img src="{$fallback}" alt="{$alt}" loading="lazy" decoding="async">
</picture>
HTML;
}
Nginx: WebP conversion on the fly
# Serve WebP if browser supports
map $http_accept $webp_suffix {
"~*webp" ".webp";
default "";
}
server {
location ~* \.(jpg|jpeg|png)$ {
add_header Vary Accept;
try_files $uri$webp_suffix $uri =404;
expires 1y;
add_header Cache-Control "public, immutable";
}
}
Implementation time
Sharp pipeline on upload with WebP/AVIF generation in multiple sizes: 2–3 days. With Nginx WebP conversion on the fly and CDN: 3–4 days.







