На главной странице было 40+ изображений отелей и направлений. Все в PNG, без адаптации под размер экрана. Мы внедрили полный пайплайн:
<!-- Адаптивные изображения с современными форматами -->
<picture>
<source
type="image/avif"
srcset="/images/hotels/paris-400.avif 400w,
/images/hotels/paris-800.avif 800w,
/images/hotels/paris-1200.avif 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 400px"
>
<source
type="image/webp"
srcset="/images/hotels/paris-400.webp 400w,
/images/hotels/paris-800.webp 800w,
/images/hotels/paris-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 400px"
>
<img
src="/images/hotels/paris-800.jpg"
alt="Отель в Париже"
loading="lazy"
decoding="async"
width="800" height="600"
>
</picture>
Для автоматической конвертации мы написали скрипт на sharp:
// scripts/optimize-images.js
const sharp = require('sharp');
const glob = require('glob');
const SIZES = [400, 800, 1200];
const FORMATS = ['avif', 'webp', 'jpg'];
async function processImage(inputPath) {
for (const size of SIZES) {
for (const format of FORMATS) {
const outputPath = inputPath
.replace('/originals/', '/optimized/')
.replace(/\.\w+$/, `-${size}.${format}`);
await sharp(inputPath)
.resize(size, null, { withoutEnlargement: true })
.toFormat(format, {
quality: format === 'avif' ? 50 : format === 'webp' ? 75 : 80
})
.toFile(outputPath);
}
}
}
glob('src/assets/originals/**/*.{png,jpg}', (err, files) => {
files.forEach(processImage);
});
Средний вес изображения упал с 380 КБ (PNG) до 28 КБ (AVIF). Атрибуты width и height на всех <img> убрали CLS, вызванный перекомпоновкой при загрузке картинок.
Оставить комментарий