Перейти к содержимому

6. Code Splitting

Code splitting — одна из самых мощных возможностей Webpack. Она позволяет разбить ваш код на несколько бандлов (чанков) и загружать их по требованию, значительно улучшая время первоначальной загрузки приложения.

Без code splitting всё приложение загружается в одном гигантском бандле:

  • Пользователь ждёт загрузки всего кода, даже если открыл только главную страницу
  • Страница /dashboard и /settings загружаются при открытии /home
  • Редко используемые фичи тормозят первый рендер

С code splitting загружается только необходимый код:

bundle.js (500 KB) → main.js (80 KB) + vendor.js (120 KB)
+ dashboard.js (60 KB — по требованию)
+ settings.js (40 KB — по требованию)
module.exports = {
entry: {
main: './src/index.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].js',
},
};
// Создаст main.js и admin.js — но общие зависимости дублируются!

Чтобы избежать дублирования общих зависимостей:

entry: {
main: { import: './src/index.js', dependOn: 'shared' },
admin: { import: './src/admin.js', dependOn: 'shared' },
shared: ['react', 'react-dom'],
}
optimization: {
splitChunks: {
chunks: 'all', // 'async' | 'initial' | 'all'
minSize: 20000, // Минимальный размер чанка (байты)
maxSize: 244000, // Максимальный размер чанка
minChunks: 1, // Минимальное количество модулей-потребителей
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: -10,
},
default: {
minChunks: 2,
reuseExistingChunk: true,
priority: -20,
},
},
},
}

Самый гибкий способ — динамические импорты через import():

// Вместо:
import HeavyComponent from './HeavyComponent';
// Используйте:
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
// Webpack автоматически создаёт отдельный чанк!

С маршрутизацией React:

import { lazy, Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}
// Имя чанка
import(/* webpackChunkName: "my-chunk" */ './module')
// Prefetch — браузер загрузит в idle time
import(/* webpackPrefetch: true */ './module')
// Preload — браузер загрузит параллельно с parent
import(/* webpackPreload: true */ './module')
// Комбинация
import(
/* webpackChunkName: "dashboard" */
/* webpackPrefetch: true */
'./pages/Dashboard'
)
optimization: {
runtimeChunk: 'single', // Webpack runtime в отдельном файле
// Предотвращает инвалидацию хешей при изменении любого файла
}

Ниже — интерактивный визуализатор code splitting. Посмотрите как разные стратегии влияют на структуру чанков.