2026-10-13 14:51:24 +08:00
|
|
|
|
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: {
|
2026-10-13 15:03:30 +08:00
|
|
|
|
// Windows 本机 es2015 曾在 rendering chunks 阶段触发 esbuild 原生崩溃
|
|
|
|
|
|
//(退出码 0xC0000409,多次复现),改 esnext 后连续构建稳定;
|
|
|
|
|
|
// 管理后台仅面向现代浏览器,不做低版本降级。
|
2026-10-13 14:51:24 +08:00
|
|
|
|
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',
|
|
|
|
|
|
'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)
|
|
|
|
|
|
}
|