perf(admin-ui): manualChunks splits vendor по domain → лучше кэширование

До: 1 chunk index-XXX.js 2 МБ / 703 КБ gzip — любой commit инвалидирует весь.

После: 10 chunks. Vendor стабилен и кэшируется, при правке кода только
main (18 КБ gz) перезагружается:

  vendor-react       194 / 60 gz   (rare changes)
  vendor-tanstack    127 / 40 gz
  vendor-forms       145 / 46 gz   (react-hook-form + ajv)
  vendor-nstart-ui  1229 /465 gz   (corp UI — brand assets + stickers)
  vendor-icons        62 / 13 gz   (phosphor)
  vendor-auth         72 / 19 gz   (oidc-client-ts + react-oidc-context)
  vendor-i18n         56 / 18 gz
  vendor-net          42 / 17 gz   (axios + crypto)
  vendor-misc         15 / 6 gz
  index (main)        67 / 19 gz   ← наш код

vendor-nstart-ui всё ещё 465 КБ gz — доминирует. Это brand assets
(stickers, lottie animations) которые eager-imported в библиотеке.
Дальнейший win требует tree-shaking в @nstart/ui — отдельная задача.
This commit is contained in:
Zimin A.N.
2026-05-05 17:32:33 +03:00
parent adc40aca22
commit 11faf086a4
+46
View File
@@ -25,4 +25,50 @@ export default defineConfig({
}, },
}, },
}, },
build: {
chunkSizeWarningLimit: 600,
rollupOptions: {
output: {
// Группировка по принципу: что меняется редко → отдельный chunk →
// браузер кэширует надолго. Что меняется часто (наш код) — в main.
manualChunks: (id) => {
if (!id.includes('node_modules')) return undefined
// React core — стабильный, основа всего
if (id.match(/node_modules\/(react|react-dom|scheduler)\//)) return 'vendor-react'
// TanStack — Router + Query, крупные но стабильные
if (id.includes('node_modules/@tanstack/')) return 'vendor-tanstack'
// @nstart/ui — самый тяжёлый: brand stickers/animations + tons of UI
// (проверяй динамически: lottie, echarts если есть, motion)
if (id.includes('node_modules/@nstart/ui')) return 'vendor-nstart-ui'
// Иконки — отдельно, ленивая загрузка эффективна
if (id.includes('node_modules/@phosphor-icons/')) return 'vendor-icons'
// Формы + JSON Schema валидация
if (id.match(/node_modules\/(react-hook-form|@hookform|ajv|ajv-formats)\//)) {
return 'vendor-forms'
}
// OIDC / auth
if (id.match(/node_modules\/(oidc-client-ts|react-oidc-context)\//)) {
return 'vendor-auth'
}
// i18next — отдельно
if (id.match(/node_modules\/(i18next|react-i18next|i18next-browser-languagedetector)\//)) {
return 'vendor-i18n'
}
// Axios + парсеры
if (id.match(/node_modules\/(axios|jose|crypto-js)\//)) return 'vendor-net'
// Остальное — в общий vendor (не должно быть много)
return 'vendor-misc'
},
},
},
},
}) })