Что это
Code-splitting — техника разбиения монолитного JavaScript-бандла на несколько отдельных чанков, которые загружаются по требованию или параллельно. Вместо одного файла bundle.js весом 800 КБ браузер получает набор небольших модулей: критический код загружается сразу, остальное — когда пользователь переходит на нужный раздел или взаимодействует с конкретным компонентом. Реализуется на уровне сборщика (Webpack, Vite, Rollup) через динамические импорты и точки разбиения маршрутов.
---
Почему это важно для SEO
Размер и время выполнения JavaScript напрямую влияют на Core Web Vitals в Google. Самый чувствительный метрик — Total Blocking Time (TBT) и его «старший брат» Interaction to Next Paint (INP). Монолитный бандл блокирует главный поток браузера: пока парсится и компилируется 1 МБ JS, страница висит без ответа на пользовательские действия. Google фиксирует это через Chrome UX Report и учитывает в ранжировании. По данным Web Almanac 2023, медианный сайт отправляет 500 КБ JavaScript на мобильных устройствах — это уже пограничная зона.
Для Яндекса JS-тяжёлые страницы создают проблемы при краулинге. Яндекс.Нейро и обычный краулер обрабатывают JavaScript, но с ограниченными ресурсами на рендеринг. Если критический контент зависит от огромного бандла, краулер может засчитать страницу как пустую или частично проиндексировать её. Кроме того, в Я.Вебмастере в разделе «Индексирование → Страницы» можно обнаружить ошибки рендеринга именно на SPA-сайтах без code-splitting. ИКС (индекс качества сайта) косвенно зависит от поведенческих факторов: медленный JS увеличивает показатель отказов, что Яндекс читает негативно.
---
Как проверить вручную
- PageSpeed Insights — вставь URL, найди раздел "Избегайте огромных полезных нагрузок сети" и "Сократите JavaScript, не используемый при начальной загрузке". Если неиспользуемый JS превышает 150 КБ, code-splitting не настроен или настроен слабо.
- Chrome DevTools → Coverage — открой DevTools (
F12), вкладка Coverage (Shift+Ctrl+P → "Coverage"). Загрузи страницу, посмотри процент неиспользованного кода в JS-файлах. Красная зона (unused) выше 60% — сигнал для сплиттинга.
- Screaming Frog — в режиме JavaScript Rendering проверь вес всех JS-ресурсов на странице (Reports → Response Codes + фильтр по JS). Суммарный вес выше 500 КБ на мобильном — проблема.
- Webpack Bundle Analyzer — если у тебя Webpack-проект, запусти:
``bash npx webpack-bundle-analyzer stats.json `` Получишь интерактивную карту бандла и увидишь, какие библиотеки занимают больше всего места.
---
Как исправить
Базовый подход: динамический импорт
// Было — всё грузится сразу
import HeavyChart from './HeavyChart';
// Стало — грузится только при необходимости
const HeavyChart = React.lazy(() => import('./HeavyChart'));Разбиение по маршрутам (React Router + React.lazy)
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Reports = lazy(() => import('./pages/Reports'));
function App() {
return (
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/reports" element={<Reports />} />
</Routes>
</Suspense>
);
}Vite — автоматический сплиттинг
В vite.config.js Vite делает route-based splitting из коробки. Дополнительно можно явно указать точки разбиения:
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
charts: ['recharts'],
}
}
}
}
}Под популярные CMS:
- WordPress (с темой на React/Vue): используй WP-скрипты (
@wordpress/scripts) — они уже включают Webpack с поддержкой динамических импортов. - Tilda: сторонний JS добавляется через блок T123 (HTML). Code-splitting здесь ограничен — выноси тяжёлые библиотеки на CDN с
defer/async. - 1C-Bitrix: в компоненте
.parameters.phpподключай JS черезCJSCoreс условием загрузки, либо переходи на Bitrix Vue с Vite-сборкой. - Webflow: встроенный конструктор не поддерживает code-splitting. Кастомный JS добавляй через
<script type="module">с динамическими импортами в секции перед</body>.
---
Типичные ошибки
- Слишком мелкое дробление. 50+ чанков по 5 КБ хуже одного файла по 300 КБ — накладные расходы на HTTP-запросы съедят выигрыш. Оптимум: чанки по 30-150 КБ.
- Сплиттинг без preload/prefetch. Разбитые чанки нужно предзагружать для критических маршрутов:
``html <link rel="prefetch" href="/chunk-reports.js"> ``
- Вендорный чанк не выделен. React, Vue, lodash — библиотеки, которые не меняются между деплоями. Без
vendorчанка браузер инвалидирует кэш при любом изменении кода.
- Lazy-loading критического контента. Если через
React.lazyзагружается Above-the-fold контент — LCP ухудшится. Разделяй критический и некритический код, а не всё подряд.
- Не проверяют результат после деплоя. После настройки сплиттинга обязательно повтори замер в PageSpeed Insights. Nпи ошибках конфигурации бандл может остаться монолитным.
---
Влияние на разные типы сайтов
Для интернет-магазинов на React/Vue (например, на headless-архитектуре) code-splitting особенно критичен: страницы категорий, карточки товаров и корзина — разные маршруты с разными зависимостями. Без сплиттинга покупатель грузит весь JS корзины на главной странице, хотя он там не нужен. Это прямо бьёт по INP и конверсии одновременно.
Контентные сайты и блоги на статических генераторах (Next.js, Nuxt, Astro) получают code-splitting почти бесплатно — фреймворки делают его по умолчанию на уровне страниц. Здесь важнее следить за тяжёлыми виджетами (карты, чаты, аналитика): их стоит выносить в dynamic import с { ssr: false }. SaaS-продукты с dashboard-интерфейсами выиграют от сплиттинга по фичам: модуль отчётов, модуль настроек, модуль биллинга — каждый в своём чанке.