PassFront
  1. PassFront
  2. База знаний
  3. Рендеринг и производительность

Как разделить React-приложение на чанки и по какому принципу это делать?

Рендеринг и производительность

Code splitting разбивает единый бандл на части, которые загружаются по необходимости. Приложение быстрее открывается, потому что браузер скачивает только нужный код.

Как это делается

Динамический import() создаёт отдельный чанк, React.lazy и Suspense подключают его как компонент:

import { lazy, Suspense } from 'react';

const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<Spinner />}>
      <Settings />
    </Suspense>
  );
}

Сборщик (Webpack, Vite, Rollup) сам выделяет отдельный файл для import().

По какому принципу делить

  1. По маршрутам — основной и самый эффективный способ: каждая страница в своём чанке.
  2. По тяжёлым редко используемым компонентам: редактор, графики, карта, модальные окна.
  3. По библиотекам: тяжёлые зависимости (например, moment, lodash) выносят в отдельный vendor-чанк, чтобы они кешировались независимо от кода приложения.
  4. По условиям: код для администратора, A/B-тестов, редких функций.

Чего не стоит делать

Делать отдельный чанк для каждого компонента. Слишком много мелких файлов — лишние запросы, задержки и ухудшение сжатия, а каждый lazy создаёт «водопад» загрузки.

Дополнительные приёмы

  • Предзагрузка: подгружать чанк при наведении на ссылку (onMouseEnter) или <link rel="prefetch">.
  • Магические комментарии Webpack: /* webpackChunkName: "settings" */.
  • Анализ состава бандла: webpack-bundle-analyzer, vite-bundle-visualizer.
  • Хеш в имени файла и долгий Cache-Control, чтобы неизменённые чанки не скачивались повторно.

Коротко для собеседования

Разделение выполняют через import() и React.lazy с Suspense. Основной принцип — делить по маршрутам и тяжёлым редким компонентам, а не дробить всё подряд: слишком много чанков замедляет загрузку.

Другие вопросы раздела