Image Kit
Полный набор инструментов оптимизации изображений для Vue 3. Один компонент <VImage> берёт на себя ленивую загрузку, переключение форматов WebP/AVIF, адаптивную арт-дирекцию, плейсхолдеры HazeHash, Blurhash и LQIP, автоматическую генерацию srcset, повтор при ошибке с экспоненциальной задержкой и плавные CSS-переходы — с нулевыми внешними runtime-зависимостями и небольшим, tree-shakeable весом (см. Размер бандла и peer-зависимости).
Помимо компонента включено всё необходимое: CLI, обрабатывающий изображения на этапе сборки (изменение размера, конвертация, генерация LQIP и HazeHash/BlurHash, запись TypeScript-манифеста), показывающий, как изображения используются в проекте, и добавляющий недостающие плейсхолдеры уже существующим <VImage>, билдеры URL для CDN для 12 провайдеров (Cloudinary, imgix, Bunny, Sanity, Storyblok, Contentful, Vercel, Cloudflare, ImageKit, TwicPics, Netlify, Gumlet) с автоопределением по хосту, модуль Nuxt 3 с автоимпортами, плагин Vite (включая обслуживание по запросу в dev-режиме), самостоятельно размещаемый сервер изображений по запросу на случай отсутствия CDN, и headless-composables для полностью кастомной разметки.
Полностью типизирован через TypeScript. Tree-shakeable (sideEffects: false). SSR-безопасен — на сервере рендерит нативный <img loading="lazy"> без единого лишнего элемента, на клиенте после гидратации подключает IntersectionObserver и рисует активный плейсхолдер.
Возможности
Плейсхолдеры
- Плейсхолдер HazeHash — предпочтительный — проп
hazehashна<VImage>: строка в 7–48 байт, которая декодируется в размытое превью с правильными пропорциями и альфа-каналом, с меньшей перцептивной ошибкой, чем у BlurHash и ThumbHash при том же размере; побеждаетblurhash,thumbhashиplaceholder; инструменты сборки делают его по умолчанию, если установлена опциональная peer-зависимостьhazehash - Плейсхолдер Blurhash — собственный декодер (без внешних пакетов); декодируется в невидимый canvas в памяти и превращается в CSS
background-imageпрямо на самом элементе — без отдельного<canvas>в DOM и без обёрток - Плейсхолдер ThumbHash — проп
thumbhashна VImage автоматически декодируется в PNG data URL; поддерживает альфа-канал; качество лучше, чем у BlurHash; флаг--thumbhashв CLI генерирует хэши на этапе сборки - LQIP blur-up — строка
data:image/…;base64,…в качествеplaceholder; ставится CSS-фоном на тот же элемент, что покажет фото, и мгновенно перекрывается им при загрузке; опциональный пропfadeInдобавляет плавное появление всего блока - Плейсхолдер среднего цвета —
placeholderMode="color"выводит сплошной средний цвет из заголовка ThumbHash (0 байт, без декодирования); либо задайтеplaceholderColorнапрямую - Плейсхолдер shimmer —
placeholderMode="shimmer"показывает анимированный CSS-скелетон (хэш не нужен); учитываетprefers-reduced-motion - Манифест плейсхолдеров — карта
src → { hazehash, blurhash, thumbhash, color, width, height }, зарегистрированная один раз (app.use(VImageKitPlugin, { placeholders })или опцияplaceholdersмодуля Nuxt); каждый<VImage>получает плейсхолдер и размеры поsrc, без пропсов на каждом использовании - Клиентские кодировщики —
encodeThumbHash()/encodeBlurhash()строят хэш изFile/Canvas/ImageDataпрямо в браузере, для мгновенных превью пользовательского контента; без зависимостей
Компонент — VImage
- Без обёртывающего элемента — рендерится как один элемент (плейсхолдер до загрузки → реальный
<img>/<picture>после), поэтомуclass/style/data-*всегда попадают на настоящую картинку, а не на промежуточный<span> - Автогенерация srcset — передайте
widths: [400, 800, 1200]; строкаsrcsetстроится автоматически; пропsizesпробрасывается - Дескрипторы плотности —
densities: [1, 2, 3](переиспользуетsrc) или{ 1: …, 2: … }(отдельные файлы на плотность) для1x/2x/3xsrcset на изображениях фиксированного размера - Фокальная точка —
focal: { x, y }отображается вobject-position, чтобы объект оставался в кадре при обрезке черезfit="cover" - Переключение WebP / AVIF —
srcкак{ avif?, webp?, fallback }рендерит<picture>с типизированными элементами<source> - Адаптивная арт-дирекция — именованные брейкпоинты отображаются в элементы
<source media="...">; запросыmax-widthиmin-widthсортируются корректно - Проп
fetchpriority—highдля LCP-изображений,lowдля находящихся ниже первого экрана; отображается в нативный HTML-атрибут - Проп
decoding—async(по умолчанию) /sync/auto; передаётся напрямую в<img> - Повтор при ошибке — проп
maxRetriesс экспоненциальной задержкой; автоматически повторяет неудачные загрузки без ручного вмешательства - Состояние ошибки — слот
#errorдля кастомного UI; встроенный вариант по умолчанию (серый прямоугольник + иконка); событие@error
Загрузка
- Ленивая загрузка через IntersectionObserver — IO вместо
loading="lazy"для точного контроля; настраиваемыеrootMarginиthreshold; SSR-безопасно - Пулинг IO — всё, что использует одинаковую конфигурацию
rootMargin+threshold, включая директивуv-lazy-img, делит один инстансIntersectionObserver; никаких накладных расходов при 50+ изображениях - Директива фонового изображения —
v-lazy-imgустанавливаетbackground-imageна любой элемент после появления во вьюпорте; плейсхолдер LQIP; настраиваемыйtransition; колбэкиonLoad/onError useBackgroundImage()— composable для ленивых + адаптивных (image-set()) фонов с blur-up; возможностьsrcset, которой не хватаетv-lazy-img
Composables и утилиты
useImage()— headless конечный автомат (idle → loading → loaded | error) + вычисляемыйimgAttrs; работает с любой разметкойuseImagePreloader()— предзагрузка пакета URL перед навигацией;{ loaded, total, progress, isComplete, errors }useBreakpoints(),useLazyLoad()— низкоуровневые composables, на которых построен самVImage, доступны для полностью кастомной разметки;useBlurhash()решает соседнюю задачу — даёт живой<canvas>-реф для тех, кому нужен именно он (самVImageстроит фон-плейсхолдер иначе, см. Blurhash-плейсхолдеры)useNetworkAware()— реактивное состояние save-data/типа соединенияbuildSizes()— построение атрибутаsizesиз объекта, ключи которого — брейкпоинты; интегрируется с брейкпоинтами плагинаgeneratePreloadLink()— генерирует HTML<link rel="preload" as="image">для SSR/NuxtuseHead
CDN-адаптеры — @macrulez/vue-image-kit/cdn
- Билдеры URL без зависимостей для Cloudinary, imgix, Bunny CDN, Sanity, Storyblok, Contentful, Vercel, Cloudflare Images, ImageKit.io, TwicPics, Netlify Image CDN, Gumlet
- Единый интерфейс
.url(path, options)/.srcset(path, widths)для всех провайдеров autoLoader()— определяет 8 из 12 провайдеров прямо по хосту URL, без ручной настройки адаптера на каждое изображение; нераспознанные хосты проходят без измененийdetectCdnProvider()— называет провайдера, к которому относится URL, или возвращаетnull
CLI — npx vue-image-kit
generate— изменяет размер изображений под несколько ширин, конвертирует в WebP/AVIF, генерирует base64 LQIP, кодирует HazeHash/BlurHash; записывает TypeScript-манифест (images.ts) со всеми предвычисленными метаданными; режим--watch,--dry-run,--skip-existing,--concurrencyscan— отчёт об использовании: каждый<VImage>,v-lazy-img,useImage()/useBackgroundImage()в проекте, источник каждого изображения (локальный импорт,public/, CDN с провайдером, удалённый URL,?vik, динамический), статистика пропсов и предупреждения; выводtable/json/md/csv,--fail-onдля CIplaceholders— BlurHash, ThumbHash или доминирующий цвет и размеры для каждого<VImage>без плейсхолдера — из локальных файлов,public/и (с--remote) CDN/удалённых URL; результат попадает в манифест плейсхолдеров или прямо в шаблон- Настройка через
vue-image-kit.config.js;sharpкак опциональная peer-зависимость — не включается в браузерный бандл
Экосистема
- Модуль Nuxt —
@macrulez/vue-image-kit/nuxt; автоматически регистрирует<VImage>иv-lazy-img; автоимпортирует каждый composable и утилиту; брейкпоинты черезruntimeConfig; может также зарегистрировать самостоятельный сервер как настоящий Nitro-роут - Плагин Vite —
@macrulez/vue-image-kit/vite; запускает обработчик CLI наbuildStart; перезапускается вhandleHotUpdateво время разработки; импорты на этапе сборки через?vikи суффиксы запроса плейсхолдеров (?placeholder=color,blurhash,?color,?size,?preview, …); опциональное обслуживание по запросу в dev-режиме - Самостоятельно размещаемый сервер по запросу —
@macrulez/vue-image-kit/server; небольшой фреймворк-агностичный обработчик запросов Node для случаев без CDN и без желания собирать build-шаг - Vue-плагин —
app.use(VImageKitPlugin, { breakpoints })регистрирует компонент и директиву глобально - Ноль внешних runtime-зависимостей — только Vue 3 как peer-зависимость; полный ESM + CJS, tree-shakeable,
sideEffects: false(см. Размер бандла и peer-зависимости)