CLI — генерация изображений
Изменение размера изображений, конвертация в WebP/AVIF, генерация LQIP и HazeHash/BlurHash, запись TypeScript-манифеста — всё одной командой.
generate — команда CLI по умолчанию. Кроме неё в CLI есть scan — отчёт о том, как изображения используются в проекте, — и placeholders, добавляющая плейсхолдеры использованиям <VImage>, которые уже есть в шаблонах. npx vue-image-kit --help перечисляет все три команды; у каждой есть своя --help с её опциями.
Требует sharp как dev-зависимость:
npm install sharp --save-devБазовое использование:
npx vue-image-kit generate \
--input ./src/images \
--output ./public/images \
--widths 400,800,1200 \
--formats jpg,webp,avif \
--manifest ./src/assets/images.tsВыводит отчёт по каждому изображению по мере работы — путь/формат/размеры/размер файла исходника, затем каждый выходной вариант со своим путём/форматом/размерами/размером файла ((existing) для файла, оставленного --skip-existing, (dry-run — not written) при --dry-run) — затем итог по пакету: количество обработанных изображений/файлов, общий входной и выходной размер, и насколько наименьший доступный формат экономит по сравнению с оригиналом в среднем (намеренно не «общий выход против общего входа» — при нескольких ширинах × форматах на изображение общий выход естественным образом в разы больше размера одного оригинала, что вводило бы в заблуждение, читаясь как «стало хуже»):
[vue-image-kit] Processing 1 image(s)…
[vue-image-kit] photo1
Input ./src/images/photo1.jpg
jpg · 1200×800 · 245.3 KB
Output
./public/images/photo1-400.jpg jpg 400×267 52.1 KB
./public/images/photo1-800.jpg jpg 800×533 118.4 KB
./public/images/photo1.jpg jpg 1200×800 198.2 KB
./public/images/photo1.webp webp 1200×800 112.9 KB
./public/images/photo1.avif avif 1200×800 79.6 KB
[vue-image-kit] Done. 1 image(s) → 5 file(s).
Input: 1 image(s), 245.3 KB total
Output: 5 file(s), 561.2 KB total
Smallest available format saves ~79% vs. original, on average
[vue-image-kit] Manifest written to ./src/assets/images.tsВсе опции:
--input <dir>· по умолчанию:./src/images. Директория-источник.--output <dir>· по умолчанию:./public/images. Выходная директория.--widths <list>· по умолчанию:400,800,1200. Выходные ширины через запятую.--formats <list>· по умолчанию:jpg,webp,avif. Выходные форматы.--quality <json>· по умолчанию:{"jpg":85,"webp":80,"avif":65}. Качество по формату.--template <str>· по умолчанию:{name}-{width}.{ext}. Шаблон имени файла ({name},{width},{ext}).--manifest <path>— записать манифестimages.tsпо этому пути.--public-path <str>· по умолчанию:/images. URL-префикс, используемый в путях манифеста.--lqip/--no-lqip· по умолчанию: включено. Генерировать base64 LQIP-плейсхолдер.--hazehash/--no-hazehash· по умолчанию: включено, если установлен пакетhazehash, иначе выключено. Генерировать строку HazeHash (предпочтительный плейсхолдер; требует пакетhazehash).--blurhash/--no-blurhash· по умолчанию: включено. Генерировать строку BlurHash.--thumbhash/--no-thumbhash· по умолчанию: выключено. Генерировать строку ThumbHash (требует dev-зависимостьthumbhash).--clean— удалить выходную директорию перед генерацией.--dry-run— предпросмотр без записи файлов.--skip-existing— пропускать уже сгенерированные файлы.--concurrency <n>· по умолчанию:4. Количество параллельных воркеров.--watch— отслеживать входную директорию и перегенерировать при изменении.--incremental/--no-incremental· по умолчанию: авто. Пропускать переобработку источника, если его mtime (или, если он изменился, хэш содержимого) совпадает с предыдущим запуском. Автоматически включается под--watch(и плагином Vite во времяvite dev), если не задано явно тем или иным способом — разовыйgenerateпо умолчанию выключен. См. Инкрементальная генерация ниже.
Файл конфигурации — создайте vue-image-kit.config.js в корне проекта, чтобы не повторять флаги:
// vue-image-kit.config.js
export default {
input: './photos',
output: './public/images',
widths: [480, 960, 1440],
formats: ['jpg', 'webp'],
manifest: './src/assets/images.ts',
publicPath: '/images',
}SVG и анимированный GIF обрабатываются иначе, чем растровые форматы — они определяются по расширению входного файла, а не по --formats:
- SVG копируется без изменений (без растеризации — он уже разрешение-независим). Запись манифеста получает
src, указывающий на копию;webp/avif/placeholder/hazehash/blurhash/thumbhash— пустые строки. - Анимированный GIF копируется как гарантированно совместимый fallback (
src), и — когдаwebpв--formats— перекодируется в анимированный WebP (полеwebp) для реальной экономии размера. AVIF пропускается: поддержка анимированного AVIF в сборкахsharp/libavif слишком непоследовательна, чтобы на неё полагаться. Плейсхолдеры LQIP/BlurHash/ThumbHash всё равно генерируются из первого кадра.
Инкрементальная генерация
--watch и buildStart/handleHotUpdate плагина Vite вызывают одну и ту же функцию generate(), что и CLI, — по умолчанию каждое изменение одного файла означает повторное сканирование и обработку всех исходных изображений, а не только того, что изменилось. Режим incremental это исправляет:
npx vue-image-kit generate --watch --incremental # уже по умолчанию под --watchДля каждого источника проверяется сохранённая запись из предыдущего запуска: mtime не изменился → полностью пропускается, без чтения, без вызова sharp. Mtime изменился (например, git checkout затронул все файлы) → используется хэш содержимого перед принятием решения — неизменённый файл переживает checkout, не вызывая ненужную переобработку. Запись — JSON-манифест по пути <output>/.vik-incremental.json — также хранит полные метаданные каждого пропущенного изображения, так что отчёт по пакету/вывод --manifest остаётся полным даже для изображений, не тронутых в этом запуске.
Изменение widths/formats/quality/template/publicPath/lqip/ hazehash/blurhash/thumbhash между запусками инвалидирует всё сразу (логируется как Config changed since last run) — не файл-за-файлом, поскольку изменение конфига может повлиять на любой или все выходы. --clean тоже инвалидирует всё, естественным образом: удаляет output, а манифест живёт внутри неё. Нет эффекта под --dry-run (ничего не записывается, поэтому нет ничего валидного для сравнения в следующий раз).
По умолчанию: выключено для разового generate (один запуск ничего не выигрывает от кэширования), автоматически включается под --watch и во время vite dev (vite build остаётся выключенным — продакшен-артефакт не должен рисковать устаревшим кэшем). Явный --incremental/--no-incremental (флаг CLI, файл конфигурации или опция плагина Vite) всегда переопределяет автоматическое значение по умолчанию в любую сторону.