Files
mdm-ordinis/ordinis-admin-ui/vite.config.ts
T

153 lines
6.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// <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 VersionBadge / UpdateBanner.
//
// Priority chain (most authoritative first):
// 1. CI_COMMIT_TAG → set ONLY on tag pipelines (e.g. "v1.3.1"). Это source
// of truth для release builds. Strip leading 'v' → "1.3.1".
// 2. package.json.version → fallback floor для local dev и branch builds.
// НЕ обновляется вручную — release flow добавит автоматический bump
// позже (release script tag + npm version в одном commit'е).
//
// __APP_TAG__ — пустая строка если не tag build. VersionBadge решает что
// показать (приоритет: serverTag → clientTag → v${clientVersion}).
//
// __APP_COMMIT__ — 8-char short SHA. CI передаёт через CI_COMMIT_SHORT_SHA
// (GitLab default 8 chars), local через `git rev-parse --short=8`.
const APP_VERSION: string = JSON.parse(
readFileSync(path.resolve(__dirname, 'package.json'), 'utf-8'),
).version
// 'none' — Dockerfile default ARG value (см. .gitlab-ci.yml passes
// --build-arg GIT_TAG="${CI_COMMIT_TAG:-none}"). Filter → пустая строка.
const RAW_TAG = process.env.CI_COMMIT_TAG ?? ''
const APP_TAG: string = RAW_TAG === 'none' ? '' : RAW_TAG.replace(/^v/, '')
// Distinguish "CI branch build" (badge → 'dev') vs "local pnpm dev" (→ 'local').
// Canonical CI signal — наличие CI_COMMIT_SHORT_SHA (GitLab CI always sets).
// process.env.CI тоже check'аем но он НЕ пробрасывается через Docker ARG'и
// (см. ordinis-admin-ui/Dockerfile), поэтому SHORT_SHA — primary detect.
const APP_CI: boolean =
Boolean(process.env.CI_COMMIT_SHORT_SHA) || process.env.CI === 'true'
const APP_COMMIT: string =
process.env.CI_COMMIT_SHORT_SHA ??
(() => {
try {
return execSync('git rev-parse --short=8 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_TAG__: JSON.stringify(APP_TAG),
__APP_CI__: JSON.stringify(APP_CI),
__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,
// secure: false нужен когда target — HTTPS endpoint с self-signed
// сертификатом (port-forward с локальным CA или внутренний cluster
// service). Для prod/staging Let's Encrypt cert validation не нужно
// отключать но игнор не вредит для dev mode.
secure: false,
// ws: true — на будущее когда Server-Sent Events / WebSocket каналы
// появятся (real-time notifications, audit stream).
ws: 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'
// 3D-graph (three.js + react-force-graph-3d + transitive deps).
// Изолирован в свой chunk, чтобы НЕ попасть в vendor-misc, который
// загружается eagerly. DictionaryGraph3D импортируется через
// React.lazy() — Rollup auto-defers этот chunk до первого
// дин-импорта. ~500kb gzipped (~600kb three.js + force graph
// wrappers), грузится только при переключении в 3D режим.
if (
id.match(
/node_modules\/(three|3d-force-graph|d3-force-3d|d3-binarytree|d3-octree|kapsule|react-kapsule|three-forcegraph|three-render-objects|react-force-graph-3d|@tweenjs|accessor-fn|index-array-by)/,
)
) {
return 'vendor-graph3d'
}
// Остальное — в общий vendor (не должно быть много)
return 'vendor-misc'
},
},
},
},
})