← Назад к вопросам

Как оптимизировать приложение с большим количеством изображений?

1.8 Middle🔥 112 комментариев
#JavaScript Core

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Оптимизация приложения с большим количеством изображений

Большое количество изображений может замедлить приложение. Я использую комплексный подход для решения этой проблемы.

1. Использование Next.js Image компонента

NextImage автоматически оптимизирует изображения с кешированием на CDN:

import Image from 'next/image';

function ProfileCard({ user }) {
  return (
    <Image
      src={user.avatar}
      alt={user.name}
      width={200}
      height={200}
      priority={false}  // lazy loading по умолчанию
      quality={85}       // баланс качества и размера
      placeholder="blur" // blur до загрузки
      blurDataURL="data:image/jpeg;base64,..."
    />
  );
}

2. Ленивая загрузка (Lazy Loading)

Загружаем изображения только когда они видны в viewport:

function ImageGallery({ images }) {
  const [visibleImages, setVisibleImages] = useState(new Set());
  const observerRef = useRef();
  
  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setVisibleImages(prev => new Set(prev).add(entry.target.id));
            observer.unobserve(entry.target);
          }
        });
      },
      { threshold: 0.1 }
    );
    
    document.querySelectorAll('.gallery-image').forEach(img => {
      observer.observe(img);
    });
    
    return () => observer.disconnect();
  }, []);
  
  return (
    <div className="gallery">
      {images.map(img => (
        <img
          key={img.id}
          id={img.id}
          className="gallery-image"
          src={visibleImages.has(img.id) ? img.url : ''}
          alt={img.alt}
          loading="lazy"
        />
      ))}
    </div>
  );
}

3. Адаптивные изображения (Responsive Images)

Показываем разные размеры для разных экранов:

import Image from 'next/image';

function ResponsiveImage({ src, alt }) {
  return (
    <Image
      src={src}
      alt={alt}
      sizes="(max-width: 640px) 100vw, (max-width: 1024px) 75vw, 50vw"
      responsive
      quality={75}
    />
  );
}

4. Сжатие изображений

Использую TinyPNG или ImageOptim для сжатия перед загрузкой на сервер:

// Клиентское сжатие перед отправкой
async function compressImage(file: File): Promise<Blob> {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = (event) => {
      const img = new Image();
      img.src = event.target?.result as string;
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d')!;
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0);
        canvas.toBlob(resolve, 'image/jpeg', 0.75);
      };
    };
  });
}

5. Форматы изображений

Оптимальная иерархия форматов:

  • WebP (лучше всего для современных браузеров)
  • JPEG (универсальный)
  • PNG (для прозрачности)
  • AVIF (новый стандарт)
<picture>
  <source srcSet="image.avif" type="image/avif" />
  <source srcSet="image.webp" type="image/webp" />
  <source srcSet="image.jpg" type="image/jpeg" />
  <img src="image.jpg" alt="description" />
</picture>

6. Виртуализация списков

Для списков с сотнями изображений использую react-window:

import { FixedSizeList as List } from 'react-window';

function ImageList({ images }) {
  const Row = ({ index, style }) => (
    <div style={style}>
      <Image
        src={images[index].url}
        alt={images[index].alt}
        width={200}
        height={200}
      />
    </div>
  );
  
  return (
    <List
      height={600}
      itemCount={images.length}
      itemSize={220}
      width="100%"
    >
      {Row}
    </List>
  );
}

7. Кеширование

Исползую Service Worker для кеширования изображений:

// service-worker.js
self.addEventListener('fetch', (event) => {
  if (event.request.url.includes('/images/')) {
    event.respondWith(
      caches.open('images-v1').then((cache) => {
        return cache.match(event.request).then((response) => {
          return response || fetch(event.request).then((res) => {
            cache.put(event.request, res.clone());
            return res;
          });
        });
      })
    );
  }
});

8. CDN для изображений

Использую Cloudinary или imgix для динамической трансформации:

const cloudinaryUrl = `https://res.cloudinary.com/${CLOUD_NAME}/image/upload/w_800,q_auto,f_webp/v${version}/${publicId}`;

<Image src={cloudinaryUrl} alt="optimized" width={800} height={600} />

9. Мониторинг производительности

function measureImagePerformance() {
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (entry.name.includes('.jpg') || entry.name.includes('.png')) {
        console.log(`${entry.name}: ${entry.duration}ms`);
      }
    }
  });
  
  observer.observe({ entryTypes: ['resource'] });
}

Итоговая стратегия

  1. Next.js Image для автооптимизации
  2. Lazy loading для изображений ниже fold
  3. Адаптивные размеры через srcset
  4. Сжатие и WebP формат
  5. Виртуализация для больших списков
  6. Service Worker кеширование
  7. CDN для трансформации
  8. Регулярный мониторинг Core Web Vitals (LCP, FID, CLS)
Как оптимизировать приложение с большим количеством изображений? | PrepBro