Image CDN — Cloudinary, imgproxy
Image CDN — специализированный CDN для изображений, который на лету выполняет ресайзинг, конвертацию формата (WebP/AVIF), оптимизацию качества и кеширование по параметрам URL, избавляя от необходимости хранить множество вариантов изображений.
Зачем нужно
Без Image CDN нужно заранее создавать и хранить десятки вариантов каждого изображения (thumbnail, webp, avif, @2x). Image CDN делает это динамически через URL-параметры и кеширует результат на edge. Значительно упрощает responsive images и ускоряет LCP.
Где используется
- E-commerce: тысячи товарных изображений в разных размерах
- CMS и блог-платформы: пользовательские загрузки
- Social: аватары, cover-фото в разных размерах
Основной контент
Cloudinary: URL-параметры трансформации
https://res.cloudinary.com/{cloud_name}/image/upload/{transformations}/{public_id}
# Базовые трансформации:
w_800,h_600,c_fill — ресайз 800x600, crop fill
f_auto — автовыбор формата (WebP/AVIF по Accept)
q_auto — автооптимизация качества
fl_progressive — прогрессивный JPEG
# Полный пример:
https://res.cloudinary.com/demo/image/upload/w_400,f_auto,q_auto/sample.jpg
Cloudinary в Next.js
// next.config.js
module.exports = {
images: {
remotePatterns: [{
protocol: 'https',
hostname: 'res.cloudinary.com',
}],
},
};
// components/ProductImage.jsx
import Image from 'next/image';
export function ProductImage({ publicId, alt }) {
return (
<Image
src={`https://res.cloudinary.com/mycloud/image/upload/f_auto,q_auto/${publicId}`}
alt={alt}
width={800}
height={600}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>
);
}
imgproxy — self-hosted альтернатива
# Docker запуск imgproxy
docker run -p 8080:8080 \
-e IMGPROXY_KEY=your_key \
-e IMGPROXY_SALT=your_salt \
-e IMGPROXY_MAX_SRC_RESOLUTION=50 \
darthsim/imgproxy
# URL формат imgproxy:
# /insecure/resize:fit:800:600/plain/https://origin.com/image.jpg@webp
// Генерация signed URL для imgproxy
const crypto = require('crypto');
function imgproxyUrl(originUrl, { width, height, format = 'webp' }) {
const processing = `resize:fit:${width}:${height}`;
const path = `/insecure/${processing}/plain/${originUrl}@${format}`;
const hmac = crypto
.createHmac('sha256', Buffer.from(process.env.IMGPROXY_KEY, 'hex'))
.update(Buffer.from(process.env.IMGPROXY_SALT, 'hex'))
.update(path)
.digest('base64url');
return `https://images.example.com/${hmac}${path}`;
}
const url = imgproxyUrl('https://storage.example.com/product.jpg', {
width: 400, height: 300, format: 'avif',
});
srcset для responsive images
<!-- С Image CDN автоматически генерируем нужные размеры -->
<img
src="https://cdn.example.com/w_800/photo.jpg"
srcset="
https://cdn.example.com/w_400/photo.jpg 400w,
https://cdn.example.com/w_800/photo.jpg 800w,
https://cdn.example.com/w_1200/photo.jpg 1200w
"
sizes="(max-width: 640px) 100vw, 800px"
alt="Photo"
loading="lazy"
decoding="async"
>
Частые ошибки
- Хранение оригинальных 5MB фото на сервере без трансформации — отдача огромных изображений
- Отсутствие
sizesатрибута при srcset — браузер загружает неподходящий размер - Трансформация при каждом запросе без кеша — Image CDN ценен именно кешированием
- Подписи URL без валидации origin — открывает SSRF через Image CDN
Связанные темы
- _MOC Производительность
- AVIF и WebP -- новые форматы
- Core Web Vitals -- LCP, FID, CLS
- Кеширование -- Cache-Control