При сборке проекта через Vite формируется набор итоговых файлов: JavaScript-бандлы, CSS-файлы, изображения, шрифты, динамические чанки и вспомогательные ресурсы. Размер этих файлов напрямую влияет на:
Контроль размера бандла становится особенно важным в крупных SPA-приложениях, библиотеках, SSR-проектах и микрофронтендах.
Vite предоставляет встроенную информацию о размере выходных файлов после выполнения production-сборки.
Команда production-сборки:
npm run build
После завершения Vite выводит таблицу с информацией о файлах:
dist/assets/index-8d91f.js 185.32 kB │ gzip: 61.22 kB
dist/assets/vendor-a2c11.js 540.10 kB │ gzip: 180.40 kB
dist/assets/index-91ab2.css 24.11 kB │ gzip: 5.30 kB
Здесь отображаются:
Физический размер файла без сжатия:
540.10 kB
Именно этот файл хранится на сервере.
Размер после gzip-компрессии:
gzip: 180.40 kB
Большинство веб-серверов отдают именно gzip-версию ресурса.
Реальный сетевой трафик обычно ближе именно к gzip-размеру.
Даже если файл хорошо сжат, браузеру всё равно необходимо:
Большой bundle способен блокировать главный поток браузера.
Если весь проект собирается в один огромный chunk:
app.js → 3 MB
браузер вынужден загружать весь код сразу, даже если пользователь открыл одну страницу.
Слабые CPU значительно медленнее выполняют parsing и compilation JavaScript.
На desktop 1 MB JS может обрабатываться быстро, а на бюджетном смартфоне — вызывать серьёзные задержки.
Vite автоматически показывает warning:
(!) Some chunks are larger than 500 kBs after minification.
По умолчанию лимит:
500 kB
Это не ошибка, а предупреждение о потенциальной проблеме производительности.
Параметр:
build.chunkSizeWarningLimit
Пример:
import { defineConfig } from 'vite'
export default defineConfig({
build: {
chunkSizeWarningLimit: 1000
}
})
Теперь warning появится только после превышения 1000 kB.
Неправильный подход:
chunkSizeWarningLimit: 5000
Это скрывает проблему, а не решает её.
Большой bundle обычно сигнализирует о:
Стандартного вывода Vite недостаточно для глубокого анализа.
Для этого используются специальные visualizer-инструменты.
Наиболее популярный вариант:
npm install --save-dev rollup-plugin-visualizer
Конфигурация:
import { defineConfig } from 'vite'
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
visualizer({
open: true,
gzipSize: true,
brotliSize: true
})
]
})
После сборки создаётся HTML-отчёт.
В нём отображаются:
Самый популярный режим.
Каждый прямоугольник — отдельный модуль.
Чем больше прямоугольник — тем тяжелее модуль.
Кольцевая структура зависимостей.
Полезна для анализа вложенности пакетов.
Отображение зависимостей в виде графа.
Удобно для поиска циклических импортов.
Часто самый большой файл:
vendor.js
Внутри обычно находятся:
Visualize-отчёт часто показывает неожиданные проблемы.
Пример:
moment.js → 300 kB
или:
lodash full build → 500 kB
Вместо:
import moment from 'moment'
лучше:
import dayjs from 'dayjs'
Плохой вариант:
import _ from 'lodash'
Лучше:
import debounce from 'lodash/debounce'
или:
import { debounce } from 'lodash-es'
Vite использует Rollup для production-сборки.
Rollup умеет удалять неиспользуемый код.
Пример:
import { debounce } from 'lodash-es'
В bundle попадёт только debounce.
Причины:
Некоторые библиотеки помечают:
{
"sideEffects": false
}
Это позволяет Rollup безопасно удалять неиспользуемые модули.
Большие CSS-файлы также ухудшают загрузку.
Причины:
Без purge CSS Tailwind может быть огромным.
Production-конфигурация:
content: [
'./index.html',
'./src/**/*.{js,ts,jsx,tsx}'
]
Неиспользуемые классы будут удалены.
Главный инструмент уменьшения initial bundle.
Пример:
const AdminPanel = () => import('./AdminPanel')
Код загрузится только при необходимости.
Vite автоматически создаёт отдельные чанки для dynamic imports.
Результат:
main.js
admin.js
chart.js
editor.js
Для роутеров:
const Home = lazy(() => import('./pages/Home'))
const Profile = lazy(() => import('./pages/Profile'))
Это резко уменьшает размер первого чанка.
Через manualChunks:
build: {
rollupOptions: {
output: {
manualChunks: {
react: ['react', 'react-dom'],
editor: ['monaco-editor'],
charts: ['chart.js']
}
}
}
}
Позволяет:
Некоторые visualizer-плагины показывают:
brotli size
Brotli обычно эффективнее gzip.
Современные CDN часто используют именно Brotli-сжатие.
Иногда bundle содержит дубли:
lodash x2
react x2
Причины:
Команды:
npm ls react
или:
npm ls lodash
Vite использует pre-bundling через esbuild.
Однако production bundle строится Rollup.
Иногда dev и production размеры заметно отличаются.
Можно включить sourcemaps:
build: {
sourcemap: true
}
Это помогает анализировать итоговый bundle.
Для production monitoring:
build: {
sourcemap: 'hidden'
}
Sourcemap создаётся, но не публикуется в браузер.
Размер бандла можно контролировать автоматически.
Например:
Можно задавать лимиты:
main.js < 200 kB
vendor.js < 500 kB
При превышении pipeline падает.
Пример:
{
"scripts": {
"analyze": "vite build"
}
}
или:
{
"scripts": {
"build:report": "vite build --mode production"
}
}
Иногда visualizer подключают только в analysis mode:
plugins: [
mode === 'analyze' && visualizer()
]
Пример:
vite build --mode analyze
Полноценный пример:
export default defineConfig(({ mode }) => ({
plugins: [
mode === 'analyze'
? visualizer({
open: true
})
: null
]
}))
Крупные SPA могут иметь разные entry points.
Важно понимать:
Иногда общий chunk становится слишком большим:
shared.js → 2 MB
Причина:
Подходы:
В library mode размер особенно важен.
Поскольку bundle будет использоваться сторонними приложениями.
В библиотеках часто исключают зависимости:
rollupOptions: {
external: ['react']
}
Это резко уменьшает размер итоговой библиотеки.
Важно убедиться, что библиотека:
Дополнительный инструмент:
npm install --save-dev source-map-explorer
Пример:
npx source-map-explorer dist/assets/*.js
Инструмент показывает:
Альтернатива visualizer:
npm install --save-dev rollup-plugin-analyzer
Некоторые анализаторы выводят статистику прямо в терминал:
Bundle size: 1.2 MB
Modules: 742
Treeshaked: 38%
Без постоянного анализа bundle постепенно разрастается.
Типичные причины:
Оптимальная стратегия:
Для SPA:
| Тип файла | Рекомендуемый размер |
|---|---|
| Initial JS | 150–300 kB gzip |
| Vendor chunk | до 500 kB gzip |
| CSS | до 100 kB gzip |
Для мобильных приложений требования обычно строже.
import { defineConfig } from 'vite'
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig(({ mode }) => ({
build: {
sourcemap: true,
chunkSizeWarningLimit: 700,
rollupOptions: {
output: {
manualChunks: {
react: ['react', 'react-dom'],
charts: ['chart.js'],
editor: ['monaco-editor']
}
}
}
},
plugins: [
mode === 'analyze'
? visualizer({
open: true,
gzipSize: true,
brotliSize: true,
filename: 'stats.html'
})
: null
]
}))