Files
ai-kefu-admin/admin/vite.config.ts
T
浅念 6afa31ec85 fix: 脚手架审查修复(dts入库保首跑/esnext注释/模板changelog清理)
- auto-imports.d.ts / components.d.ts 出 .gitignore 并入库(已重新生成):新克隆/CI 首跑 pnpm build 直接可用,Phase 4 部署依赖
- vite.config.ts build.target=esnext 补注释:Windows 本机 es2015 曾触发 esbuild 0xC0000409 原生崩溃,改后稳定;管理后台仅面向现代浏览器
- 删除模板自带 CHANGELOG.md / CHANGELOG.zh-CN.md(约 650 行 x2,与本项目无关)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 15:03:30 +08:00

179 lines
5.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.
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { fileURLToPath } from 'url'
import vueDevTools from 'vite-plugin-vue-devtools'
import viteCompression from 'vite-plugin-compression'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import ElementPlus from 'unplugin-element-plus/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import tailwindcss from '@tailwindcss/vite'
// import { visualizer } from 'rollup-plugin-visualizer'
export default ({ mode }: { mode: string }) => {
const root = process.cwd()
const env = loadEnv(mode, root)
const {
VITE_VERSION,
VITE_PORT,
VITE_BASE_URL,
VITE_API_URL,
VITE_API_PROXY_URL,
VITE_TENANT_PREVIEW_HOST
} = env
console.log(`🚀 API_URL = ${VITE_API_URL}`)
console.log(`🚀 VERSION = ${VITE_VERSION}`)
// 代理策略(后端 TenantHostMiddleware 事实源 app/platform/host_middleware.py:
// 仅 /health 精确与 /api/platform/ 前缀豁免租户 Host 解析,其余按 Host 找租户):
// - /api/platform/*:豁免前缀,changeOrigin 直转即可(Host=127.0.0.1:8018 无碍);
// - /api/public/*:品牌/头像公开端点依赖租户 Host——用 headers.Host 改写成
// VITE_TENANT_PREVIEW_HOST(种子租户域名),changeOrigin 必须为 false
// 否则 Host 会被改回目标地址使解析 404;
// - /static/*:静态资源同样过租户解析,与 /api/public 同策略。
// 注意对象键序:更长的 /api/public 前缀必须排在 /api 之前(http-proxy 按序首配命中)。
const tenantHostProxy = {
target: VITE_API_PROXY_URL,
changeOrigin: false,
headers: { Host: VITE_TENANT_PREVIEW_HOST }
}
return defineConfig({
define: {
__APP_VERSION__: JSON.stringify(VITE_VERSION)
},
base: VITE_BASE_URL,
server: {
port: Number(VITE_PORT),
proxy: {
'/api/public': { ...tenantHostProxy },
'/api': {
target: VITE_API_PROXY_URL,
changeOrigin: true
},
'/static': { ...tenantHostProxy }
},
host: true
},
// 路径别名
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@views': resolvePath('src/views'),
'@imgs': resolvePath('src/assets/images'),
'@icons': resolvePath('src/assets/icons'),
'@utils': resolvePath('src/utils'),
'@stores': resolvePath('src/store'),
'@styles': resolvePath('src/assets/styles')
}
},
build: {
// Windows 本机 es2015 曾在 rendering chunks 阶段触发 esbuild 原生崩溃
//(退出码 0xC0000409,多次复现),改 esnext 后连续构建稳定;
// 管理后台仅面向现代浏览器,不做低版本降级。
target: 'esnext',
outDir: 'dist',
chunkSizeWarningLimit: 2000,
minify: 'terser',
terserOptions: {
compress: {
// 生产环境去除 console
drop_console: true,
// 生产环境去除 debugger
drop_debugger: true
}
},
dynamicImportVarsOptions: {
warnOnError: true,
exclude: [],
include: ['src/views/**/*.vue']
}
},
plugins: [
vue(),
tailwindcss(),
// 自动按需导入 API
AutoImport({
imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
dts: 'src/types/import/auto-imports.d.ts',
resolvers: [ElementPlusResolver()],
eslintrc: {
enabled: true,
filepath: './.auto-import.json',
globalsPropValue: true
}
}),
// 自动按需导入组件
Components({
dts: 'src/types/import/components.d.ts',
resolvers: [ElementPlusResolver()]
}),
// 按需定制主题配置
ElementPlus({
useSource: true
}),
// 压缩
viteCompression({
verbose: false, // 是否在控制台输出压缩结果
disable: false, // 是否禁用
algorithm: 'gzip', // 压缩算法
ext: '.gz', // 压缩后的文件名后缀
threshold: 10240, // 只有大小大于该值的资源会被处理 10240B = 10KB
deleteOriginFile: false // 压缩后是否删除原文件
}),
vueDevTools()
// 打包分析
// visualizer({
// open: true,
// gzipSize: true,
// brotliSize: true,
// filename: 'dist/stats.html' // 分析图生成的文件名及路径
// }),
],
// 依赖预构建:避免运行时重复请求与转换,提升首次加载速度
optimizeDeps: {
include: [
'echarts/core',
'echarts/charts',
'echarts/components',
'echarts/renderers',
'crypto-js',
'element-plus/es',
'element-plus/es/components/*/style/css',
'element-plus/es/components/*/style/index'
]
},
css: {
preprocessorOptions: {
// sass variable and mixin
scss: {
additionalData: `
@use "@styles/core/el-light.scss" as *;
@use "@styles/core/mixin.scss" as *;
`
}
},
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove()
}
}
}
}
]
}
}
})
}
function resolvePath(paths: string) {
return path.resolve(__dirname, paths)
}