JavaRush /Курсы /Модуль 3: React /Отложенная загрузка изображений и ресурсов

Отложенная загрузка изображений и ресурсов

Модуль 3: React
10 уровень , 7 лекция
Открыта

Что такое отложенная загрузка и зачем она нужна?

Отложенная загрузка (lazy loading) — это техника, которая позволяет загружать ресурсы только тогда, когда они становятся необходимыми. Например, изображения, которые находятся за пределами видимой области страницы, можно не загружать сразу, а подгружать, когда пользователь скроллит вниз и они попадают в поле зрения.

Почему это важно?

  1. Скорость загрузки: меньше ресурсов загружается сразу, поэтому страница отображается быстрее.
  2. Экономия трафика: пользователи загружают только те ресурсы, которые им действительно нужны.
  3. Лучший пользовательский опыт: всё работает быстрее, а пользователям не приходится ожидать.

Согласно исследованиям, если страница загружается больше трёх секунд, 40% пользователей закрывают её. Оптимизированная загрузка помогает избежать этого!

Базовая идея реализации

Отложенная загрузка часто применяется к изображениям. Представьте длинный список карточек с фото, где фотографии изначально не загружаются. Изображение загружается только тогда, когда оно попадает в область видимости экрана (viewport).

Для реализации отложенной загрузки мы будем использовать комбинацию JavaScript, React и HTML5 API, а также познакомимся с библиотеками, которые могут упростить эту задачу.

Реализация отложенной загрузки изображений

Существует два популярных способа реализации:

  • Intersection Observer API: нативный способ отслеживать, когда элемент попадает в область видимости.
  • Плейсхолдеры: сначала показываются "заглушки" (плейсхолдеры), а изображение загружается позже.

Создаём базовый компонент для lazy loading

Мы начнём с компонента, который загружает изображения только тогда, когда они попадают в область видимости. Используем Intersection Observer API.

Шаг 1: Настройка проекта

Мы продолжаем работать с нашим текущим React-приложением. Убедитесь, что всё настроено.

Файл: LazyImage.tsx

import React, { useState, useEffect, useRef } from "react";

// Интерфейс для пропсов
interface LazyImageProps {
  src: string; // URL изображения
  alt?: string; // Альтернативный текст
  placeholder?: string; // Заглушка, которая будет отображаться до загрузки
}

// LazyImage компонент
const LazyImage: React.FC<LazyImageProps> = ({ src, alt = "", placeholder }) => {
  const [isVisible, setIsVisible] = useState(false); // Видимость элемента
  const imgRef = useRef<HTMLImageElement | null>(null); // Реф для изображения

  // Хук useEffect для наблюдения за элементом
  useEffect(() => {
    const observer => new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setIsVisible(true);
            observer.disconnect(); // Останавливаем наблюдение
          }
        });
      },
      {
        threshold: 0.1, // 10% элемента должны быть видимы
      }
    );

    const refElement = imgRef.current;

    if (refElement) {
      observer.observe(refElement);
    }

    return () => observer.disconnect();
  }, []);

  return (
    <img
      ref={imgRef}
      src={isVisible ? src : placeholder} // Отображаем изображение или плейсхолдер
      alt={alt}
      style={{
        width: "100%",
        height: "auto",
        transition: "opacity 0.5s", // Плавный переход
      }}
    />
  );
};

export default LazyImage;

Использование компонента LazyImage

Теперь давайте применим наш компонент к списку изображений.

Файл: App.tsx

import React from "react";
import LazyImage from "./LazyImage";

const App: React.FC = () => {
  const images = [
    "https://via.placeholder.com/600/92c952",
    "https://via.placeholder.com/600/771796",
    "https://via.placeholder.com/600/24f355",
    "https://via.placeholder.com/600/d32776",
  ];

  return (
    <div style={{ padding: "20px" }}>
      {images.map((image, index) => (
        <LazyImage
          key={index}
          src={image}
          alt={`Image ${index + 1}`}
          placeholder="https://via.placeholder.com/600/CCCCCC"
        />
      ))}
</div>
);
};

export default App;

Теперь наш список изображений загружается только тогда, когда пользователь прокручивает страницу и изображение попадает в область видимости!

Улучшение пользовательского опыта с помощью фальшивых заглушек

Мы уже добавили плейсхолдеры. Однако, чтобы сделать загрузку более плавной, можно добавить эффект размытия при появлении изображения.

Измените LazyImage.tsx:

return (
  <img
    ref={imgRef}
    src={isVisible ? src : placeholder}
    alt={alt}
    style={{
      width: "100%",
      height: "auto",
      filter: isVisible ? "none" : "blur(10px)",
      transition: "filter 0.5s",
    }}
  />
);

Теперь при появлении изображение будет плавно переходить из размытого состояния в чёткое. Это визуально приятно и добавляет интерактивности.

Библиотеки для отложенной загрузки

Реализовать всё с нуля — это здорово. Но иногда удобно использовать готовые решения. Вот несколько популярных библиотек:

React-lazyload

Одна из самых простых библиотек для отложенной загрузки. Она предоставляет компоненты для создания lazy loading.

npm install react-lazyload

Использование:

import LazyLoad from "react-lazyload";

const App: React.FC = () => {
  return (
    <LazyLoad height={200} offset={100}>
      <img src="https://via.placeholder.com/600/92c952" alt="Lazy Loaded" />
    </LazyLoad>
  );
};

Особенности и типичные ошибки

При реализации отложенной загрузки могут возникнуть ошибки:

  1. Неправильное определение области видимости: если IntersectionObserver отслеживает что-то не то, проверьте настройки threshold и rootMargin.

  2. Слишком много изображений: если у вас тысячи изображений, лучше использовать оптимизированные инструменты, такие как react-lazyload.

  3. Преждевременная загрузка: иногда изображения загружаются заранее. Проверьте, правильно ли вы используете useRef и обновляете состояние.

Отложенная загрузка необходима в реальных проектах: от онлайн-магазинов с тысячами товаров до соцсетей. На собеседованиях такие задачи могут показаться простыми, но знание нюансов и готовность объяснить выбор подхода добавят вам очков как кандидату.

1
Задача
Модуль 3: React, 10 уровень, 7 лекция
Недоступна
Создание компонента с отложенной загрузкой изображений
Создание компонента с отложенной загрузкой изображений
1
Задача
Модуль 3: React, 10 уровень, 7 лекция
Недоступна
Добавление плейсхолдера при загрузке
Добавление плейсхолдера при загрузке
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Антон Уровень 90
31 июля 2025
Кажется опечатка const observer => new IntersectionObserver . Поменять на const observer = new IntersectionObserver(