Sharp — быстрая обработка изображений без компромиссов
Серверная обработка изображений становится узким местом, когда пользователи загружают RAW с камер или фото 12 Мп с телефона. Jimp потребляет 200+ МБ на одно изображение, ImageMagick требует системной установки и нестабилен под нагрузкой. Мы сталкивались с проектом, где 10 одновременных загрузок клали сервер из-за OOM. Решение — Sharp на базе libvips. Он обрабатывает изображения потоково, без загрузки полного файла в память, и в 4–5 раз быстрее аналогов.
Почему Sharp быстрее аналогов?
Sharp не держит весь файл в памяти — он разбирает его по кускам, применяет операции и сразу пишет результат. Это даёт вдвое меньшее потребление памяти при той же нагрузке. Сравните с ImageMagick: тот конвертирует через временные файлы на диске, что замедляет работу в высоконагруженных системах. В наших тестах Sharp обработал 1000 изображений (1920×1080 → 800px WebP) за 12 секунд — ImageMagick понадобилось 38 секунд.
| Библиотека | Потребление памяти на 1 изображение | Время конвертации (1000 шт.) |
|---|---|---|
| Sharp | 20–30 МБ | 12 с |
| Jimp | 150–250 МБ | 45 с |
| ImageMagick | 100–150 МБ + I/O | 38 с |
Как Sharp защищает от decompression bomb?
Decompression bomb — изображение с огромными размерами (например, 100k×100k пикселей), которое при попытке загрузки выделяет всю память. Sharp позволяет проверить метаданные до полной загрузки: вызовите metadata() и отклоните файл, если ширина × высота превышает лимит (например, 50 Мп). Это предотвращает OOM без лишних затрат.
Как мы реализуем интеграцию
На одном из проектов (интернет-магазин одежды) требовалось автоматически конвертировать загружаемые фото в WebP с несколькими размерами, сохранять EXIF для SEO и не допускать decompression bomb. Мы построили пайплайн:
- Multer сохраняет файл в памяти (buffer).
- Sharp читает метаданные — если площадь > 50 Мп, отклоняем.
- Применяем
.rotate()для автоматического поворота по EXIF. - Через
clone()создаём три ветки: thumbnail (150×150 cover), medium (800px), large (1920px). - Каждую ветку конвертируем в WebP (quality 82, effort 4) и сохраняем в S3.
- Возвращаем JSON со ссылками.
Результат: время загрузки упало с 3 секунд до 0.8, сервер выдерживает 50 одновременных запросов.
Выбор формата: WebP или AVIF?
| Формат | Степень сжатия (относительно JPEG) | Поддержка браузерами (2025) | Потребление CPU |
|---|---|---|---|
| WebP | ~30% меньше JPEG | 96% | Умеренное |
| AVIF | ~50% меньше JPEG | 87% | Высокое |
| JPEG XL | ~60% меньше JPEG | 10% | Среднее |
Для большинства проектов WebP — оптимальный баланс. AVIF выбирают, когда размер критичен, а CPU не жмут.
Настройка concurrency в продакшене
Sharp использует все ядра CPU по умолчанию, что может перегрузить сервер. Рекомендуем ограничить:
sharp.concurrency(2) // два потока Также используйте очередь через p-limit для контроля одновременных обработок, контролируя concurrency.
Процесс работы
- Аналитика: изучаем текущий пайплайн, замеряем нагрузку, определяем целевые форматы и разрешения.
- Проектирование: выбираем стратегию кэширования (CDN, заголовки Cache-Control), настраиваем конвейер с учётом вашего стека (Express, S3, Cloudflare).
- Реализация: пишем код с обработкой ошибок, защитой от decompression bomb, интеграцией с Multer или busboy.
- Тестирование: нагрузочный тест с 1000 изображений, проверка всех форматов и разрешений.
- Деплой: документация по развёртыванию, мониторинг (метрики времени обработки, памяти).
Сроки ориентировочно: от 2 до 5 рабочих дней в зависимости от сложности интеграции (количество форматов, S3, водяной знак). Стоимость рассчитывается индивидуально после аудита вашего проекта. Экономия на серверных ресурсах — до 70% затрат на CPU и память.
Что входит в работу
- Готовый пайплайн обработки изображений (resize, конвертация, водяной знак).
- Интеграция с вашим веб-сервером (Express, Fastify, Next.js API routes).
- Документация по деплою и настройке (переменные окружения, лимиты форков Sharp).
- Доступ к репозиторию с кодом.
- Гарантия поддержки в течение 2 недель после сдачи.
Типичные ошибки при интеграции
- Забыли про concurrency: Sharp использует все ядра — в продакшене ограничьте
sharp.concurrency(2)и очередь через p-limit. - Не проверяете формат через metadata: MIME-тип можно подделать. Sharp автоматически определит реальный формат — используйте
meta.format. - Сохраняете EXIF с GPS: при публичной публикации удаляйте метаданные
.withMetadata(false), иначе утечка координат.
Оценим ваш проект бесплатно — просто пришлите текущий код обработки. Получите консультацию по оптимизации изображений без покупки дорогих библиотек.
// Пример конвейера с защитой от decompression bomb async function safeProcess(buffer) { try { const meta = await sharp(buffer).metadata() if (meta.width * meta.height > 50_000_000) { throw new Error('Image too large: exceeds 50MP limit') } return await sharp(buffer) .rotate() .resize(2000, 2000, { fit: 'inside', withoutEnlargement: true }) .webp({ quality: 82 }) .toBuffer() } catch (err) { if (err.message.includes('Input buffer contains unsupported image format')) { throw new TypeError('Unsupported image format') } throw err } } Наш опыт: 10+ лет в веб-разработке, 50+ проектов с интеграцией Sharp. Гарантируем совместимость с вашим стеком.







