111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
/// <reference types="vitest" />
|
||
import { defineConfig } from 'vite'
|
||
import react from '@vitejs/plugin-react'
|
||
import tailwindcss from '@tailwindcss/vite'
|
||
import { TanStackRouterVite } from '@tanstack/router-vite-plugin'
|
||
import path from 'path'
|
||
import { execSync } from 'node:child_process'
|
||
import { readFileSync } from 'node:fs'
|
||
|
||
// Build identity injected at compile time. Used by /update banner — client
|
||
// сравнивает свой commit с server's /api/v1/version и показывает "Доступна
|
||
// новая версия" если различаются.
|
||
//
|
||
// Fallbacks для CI / sandboxed builds где git unavailable: env var override,
|
||
// затем "unknown".
|
||
const APP_VERSION: string = JSON.parse(
|
||
readFileSync(path.resolve(__dirname, 'package.json'), 'utf-8'),
|
||
).version
|
||
const APP_COMMIT: string =
|
||
process.env.CI_COMMIT_SHORT_SHA ??
|
||
(() => {
|
||
try {
|
||
return execSync('git rev-parse --short HEAD', { stdio: ['ignore', 'pipe', 'ignore'] })
|
||
.toString()
|
||
.trim()
|
||
} catch {
|
||
return 'unknown'
|
||
}
|
||
})()
|
||
const APP_BUILT_AT: string = new Date().toISOString()
|
||
|
||
export default defineConfig({
|
||
define: {
|
||
__APP_VERSION__: JSON.stringify(APP_VERSION),
|
||
__APP_COMMIT__: JSON.stringify(APP_COMMIT),
|
||
__APP_BUILT_AT__: JSON.stringify(APP_BUILT_AT),
|
||
},
|
||
test: {
|
||
environment: 'jsdom',
|
||
setupFiles: ['./src/test/setup.ts'],
|
||
globals: true,
|
||
css: false,
|
||
},
|
||
plugins: [
|
||
TanStackRouterVite({ routesDirectory: 'src/routes', generatedRouteTree: 'src/routeTree.gen.ts' }),
|
||
react(),
|
||
tailwindcss(),
|
||
],
|
||
resolve: {
|
||
alias: {
|
||
'@': path.resolve(__dirname, 'src'),
|
||
},
|
||
},
|
||
server: {
|
||
host: '0.0.0.0',
|
||
port: 5173,
|
||
proxy: {
|
||
'/api': {
|
||
target: process.env.VITE_API_PROXY ?? 'http://localhost:8080',
|
||
changeOrigin: true,
|
||
},
|
||
},
|
||
},
|
||
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'
|
||
},
|
||
},
|
||
},
|
||
},
|
||
})
|