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

Как работает lazy?

2.2 Middle🔥 151 комментариев
#React

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

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

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

React.lazy и динамическая загрузка компонентов

React.lazy() позволяет загружать компоненты асинхронно при необходимости, что значительно улучшает производительность приложения. Это процесс называется code-splitting и экономит пропускную способность при первоначальной загрузке.

1. Базовое использование React.lazy

// Импорт с использованием React.lazy
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

// Компонент загружается только когда он попытается отобразиться
function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <HeavyComponent />
    </Suspense>
  );
}

React.lazy принимает функцию, которая возвращает Promise с динамическим импортом. Suspense показывает fallback пока компонент загружается.

2. Code-splitting со маршрутизацией

import React, { Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

// Каждая страница загружается отдельно
const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));
const Contact = React.lazy(() => import('./pages/Contact'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading page...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

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

3. Обработка ошибок при загрузке

// Error boundary для обработки ошибок загрузки
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.error('Failed to load component:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <div>Failed to load component. Please refresh.</div>;
    }
    return this.props.children;
  }
}

// Использование
<ErrorBoundary>
  <Suspense fallback={<div>Loading...</div>}>
    <LazyComponent />
  </Suspense>
</ErrorBoundary>

Error Boundary перехватывает ошибки при загрузке компонента и отображает резервный интерфейс.

4. Ленивая загрузка в Next.js

import dynamic from 'next/dynamic';

// Базовое динамическое включение
const DynamicComponent = dynamic(() => import('../components/Hello'), {
  loading: () => <p>Loading...</p>,
  ssr: false // отключить SSR для этого компонента
});

// С предварительной загрузкой
const HeavyChart = dynamic(
  () => import('../components/Chart'),
  { 
    loading: () => <div>Loading chart...</div>,
    ssr: false 
  }
);

export default function Page() {
  return <DynamicComponent />;
}

Next.js имеет встроенный dynamic() для более удобной работы с lazy loading, особенно с SSR.

5. Практический пример с модальным окном

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  
  // Модальное окно загружается только если isModalOpen = true
  const Modal = React.lazy(() => import('./Modal'));
  
  return (
    <div>
      <button onClick={() => setIsModalOpen(true)}>Open Modal</button>
      
      {isModalOpen && (
        <Suspense fallback={<div>Loading modal...</div>}>
          <Modal onClose={() => setIsModalOpen(false)} />
        </Suspense>
      )}
    </div>
  );
}

Этот паттерн экономит трафик - код модального окна загружается только при его открытии.

6. Предварительная загрузка (preloading)

// Функция для предварительной загрузки
function preloadComponent(Component) {
  Component.render();
}

const HeavyComponent = React.lazy(() => import('./Heavy'));

function App() {
  // Предзагрузить компонент когда пользователь наводит мышь
  const handleMouseEnter = () => {
    // Инициирует загрузку без отображения
    preloadComponent(HeavyComponent);
  };
  
  return (
    <div onMouseEnter={handleMouseEnter}>
      <Suspense fallback={<div>Loading...</div>}>
        <HeavyComponent />
      </Suspense>
    </div>
  );
}

Предварительная загрузка уменьшает задержку, когда пользователь действительно нужен компонент.

7. Как работает процесс lazy loading

// Пошагово, что происходит:

// 1. React.lazy() возвращает компонент, который поддерживает suspend
const LazyComp = React.lazy(() => import('./Component'));

// 2. При первой попытке отрисовать:
// - React вызывает функцию import('./Component')
// - Это возвращает Promise
// - React ловит Promise и выбрасывает его (suspend)

// 3. Suspense ловит Promise
// - Показывает fallback
// - Ждет когда Promise разрешится

// 4. Когда Promise разрешается:
// - Компонент загружен
// - React пытается отрисовать снова
// - На этот раз компонент готов

// 5. Компонент отображается нормально

// Весь процесс обработан автоматически React'ом

8. Оптимизация bundler для lazy loading

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10
        },
        common: {
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true
        }
      }
    }
  }
};

Правильная конфигурация bundler'а критична для эффективного code-splitting.

Ключевые показатели производительности

// Инструменты для отслеживания улучшений

// Web Vitals
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

getLCP(console.log); // Largest Contentful Paint
getFID(console.log); // First Input Delay
getCLS(console.log); // Cumulative Layout Shift

Лучшие практики

  1. Используй lazy для больших компонентов - экономит 100KB+ в main bundle
  2. Оборачивай в Suspense - всегда показывай индикатор загрузки
  3. Используй Error Boundary - обрабатывай ошибки загрузки
  4. Code-split по маршрутам - основной способ использования
  5. Мониторь Web Vitals - отслеживай улучшения LCP и CLS
  6. Предзагружай критичные компоненты - избегай неожиданных задержек

Lazy loading это мощный инструмент для оптимизации производительности Front-End приложений, особенно для пользователей на медленных сетях.

Как работает lazy? | PrepBro