Files
gsfdc/admin/vite.config.ts
T
wuzilongandCursor 608afb88ea chore: 同步主分支本地改动与个人开发工具链
纳入 personal-dev/OpenSpec 配置、管理端与教育 Demo 界面调整、工作人员 JWT 默认 7 天,以及参考资料与代理文档更新。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-10 17:14:52 +08:00

179 lines
5.2 KiB
TypeScript
Executable File

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { existsSync, readdirSync } from 'fs'
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'
/**
* Element Plus 按需样式不会在启动扫描时全部可见;首次进入新页面会触发
* “发现新依赖 → 重预构建 → 旧 hash 请求 504 Outdated Optimize Dep”。
* 这里同步枚举全部 style 入口,避免路由切换中途重建。
*/
function elementPlusStyleEntries(): string[] {
const dir = path.resolve(__dirname, 'node_modules/element-plus/es/components')
if (!existsSync(dir)) return []
const entries: string[] = []
for (const name of readdirSync(dir)) {
const styleDir = path.resolve(dir, name, 'style')
if (existsSync(path.resolve(styleDir, 'css.mjs'))) {
entries.push(`element-plus/es/components/${name}/style/css`)
}
if (existsSync(path.resolve(styleDir, 'index.mjs'))) {
entries.push(`element-plus/es/components/${name}/style/index`)
}
}
return entries
}
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 } = env
console.log(`🚀 API_URL = ${VITE_API_URL}`)
console.log(`🚀 VERSION = ${VITE_VERSION}`)
return defineConfig({
define: {
__APP_VERSION__: JSON.stringify(VITE_VERSION)
},
base: VITE_BASE_URL,
server: {
port: Number(VITE_PORT),
proxy: {
'/api': {
target: VITE_API_PROXY_URL,
changeOrigin: true
}
},
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: {
target: 'es2015',
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',
'xlsx',
'xgplayer',
'crypto-js',
'file-saver',
'vue-img-cutter',
'element-plus/es',
...elementPlusStyleEntries()
]
},
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)
}