На заре сборщиков мы жили в достаточно простом мире: был один entry point — был один большой выходной файл. Это работало нормально, пока проекты не начали разрастаться. Оказалось, что огромный бандл — это отсутствие нормального кеширования, необходимость перекачивать весь код заново при любых изменениях и замедления загрузки.
Из этой боли родилась идея code splitting. Какое-то время для этого использовали только lazy-импорты, и разработчики сами должны были подсказывать сборщику, где стоит разрезать проект. Но со временем стало понятно, что это ограничивает архитектуру. Поэтому последние версии Webpack (начиная с 4-й) пошли другим путём: они научились анализировать граф модулей глубже и стали достаточно “умными”, чтобы делить код даже без lazy-импортов.
Магия спрятана в настройках оптимизации. Например, можно включить splitChunks для всех чанков и указать желаемый максимальный размер:
module.exports = {
entry: './src/index.js',
optimization: {
splitChunks: {
chunks: 'all',
maxSize: 8000
}
},
...
}
Теперь Webpack смотрит на итоговый entry-чанк, понимает, что он слишком большой, и начинает аккуратно вырезать из него фрагменты модулей, формируя дополнительные чанки. Импорт остаётся обычным, при этом код распределяется по нескольким файлам, которые браузер загрузит параллельно и будет кешировать независимо.
Результат на моём маленьком демо:
Было: main.js (24KB)
Стало:
├── main.js (3.3KB)
├── 648.js (3.1KB)
├── 14.js (2.6KB)
├── 339.js (2.2KB)
└── 812.js (1.4KB)
Все файлы будут загружены сразу, и это ожидаемое поведение: вебпак просто оптимизирует структуру бандла, но не делает его динамическим. Для ленивой загрузки по-прежнему нужны
import(). Но в ситуациях, когда проект сложно разделить руками, а хочется хотя бы улучшить кеш и скорость начальной загрузки за счёт нескольких параллельных файлов, такая оптимизация работает хорошо — особенно в сочетании с переходом на HTTP/2.При этом полностью отказываться от объединения модулей (.ts, .css, .tsx и т.д.) в чанки не стоит даже при работе с HTTP/2 — это показывают исследования и результаты бенчмарков (пример). Поэтому code splitting в Webpack является хорошим компромиссным решением, которое повышает скорость загрузки.
UPD: В комментариях также есть интересные рассуждения на тему причин появления code splitting и его эффективности.