Skip to content

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/3x srcset на изображениях фиксированного размера
  • Фокальная точка — 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/Nuxt useHead

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, --concurrency
  • scan — отчёт об использовании: каждый <VImage>, v-lazy-img, useImage()/useBackgroundImage() в проекте, источник каждого изображения (локальный импорт, public/, CDN с провайдером, удалённый URL, ?vik, динамический), статистика пропсов и предупреждения; вывод table/json/md/csv, --fail-on для CI
  • placeholders — 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-зависимости)