270 lines
10 KiB
TypeScript
270 lines
10 KiB
TypeScript
|
import { defineConfig, loadEnv } from 'vite'
|
|||
|
import vue from '@vitejs/plugin-vue'
|
|||
|
import path from 'path'
|
|||
|
import viteCompression from 'vite-plugin-compression'
|
|||
|
import Components from 'unplugin-vue-components/vite'
|
|||
|
import AutoImport from 'unplugin-auto-import/vite'
|
|||
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
|||
|
import { fileURLToPath } from 'url'
|
|||
|
// import viteImagemin from 'vite-plugin-imagemin'
|
|||
|
// import { visualizer } from 'rollup-plugin-visualizer'
|
|||
|
|
|||
|
// https://devtools.vuejs.org/getting-started/introduction
|
|||
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
|||
|
|
|||
|
export default ({ mode }) => {
|
|||
|
const root = process.cwd()
|
|||
|
const env = loadEnv(mode, root)
|
|||
|
const { VITE_VERSION, VITE_PORT, VITE_BASE_URL, VITE_API_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: parseInt(VITE_PORT),
|
|||
|
proxy: {
|
|||
|
'/api': {
|
|||
|
target: VITE_API_URL,
|
|||
|
changeOrigin: true,
|
|||
|
rewrite: (path) => path.replace(/^\/api/, '')
|
|||
|
}
|
|||
|
},
|
|||
|
host: true
|
|||
|
},
|
|||
|
// 路径别名
|
|||
|
resolve: {
|
|||
|
alias: {
|
|||
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|||
|
'@views': resolvePath('src/views'),
|
|||
|
'@imgs': resolvePath('src/assets/img'),
|
|||
|
'@icons': resolvePath('src/assets/icons'),
|
|||
|
'@utils': resolvePath('src/utils'),
|
|||
|
'@stores': resolvePath('src/store'),
|
|||
|
'@plugins': resolvePath('src/plugins'),
|
|||
|
'@styles': resolvePath('src/assets/styles')
|
|||
|
}
|
|||
|
},
|
|||
|
build: {
|
|||
|
target: 'es2015',
|
|||
|
outDir: 'dist',
|
|||
|
chunkSizeWarningLimit: 2000,
|
|||
|
minify: 'terser',
|
|||
|
terserOptions: {
|
|||
|
compress: {
|
|||
|
drop_console: true, // 生产环境去除 console
|
|||
|
drop_debugger: true // 生产环境去除 debugger
|
|||
|
}
|
|||
|
},
|
|||
|
rollupOptions: {
|
|||
|
output: {
|
|||
|
manualChunks: {
|
|||
|
vendor: ['vue', 'vue-router', 'pinia', 'element-plus']
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
dynamicImportVarsOptions: {
|
|||
|
warnOnError: true,
|
|||
|
exclude: [],
|
|||
|
include: ['src/views/**/*.vue']
|
|||
|
}
|
|||
|
},
|
|||
|
plugins: [
|
|||
|
vue(),
|
|||
|
// 自动导入 components 下面的组件,无需 import 引入
|
|||
|
Components({
|
|||
|
deep: true,
|
|||
|
extensions: ['vue'],
|
|||
|
dirs: ['src/components'], // 自动导入的组件目录
|
|||
|
resolvers: [ElementPlusResolver()],
|
|||
|
dts: 'src/types/components.d.ts' // 指定类型声明文件的路径
|
|||
|
}),
|
|||
|
AutoImport({
|
|||
|
imports: ['vue', 'vue-router', '@vueuse/core', 'pinia'],
|
|||
|
resolvers: [ElementPlusResolver()],
|
|||
|
dts: 'src/types/auto-imports.d.ts',
|
|||
|
eslintrc: {
|
|||
|
// 这里先设置成true然后pnpm dev 运行之后会生成 .auto-import.json 文件之后,在改为false
|
|||
|
enabled: true,
|
|||
|
filepath: './.auto-import.json',
|
|||
|
globalsPropValue: true
|
|||
|
}
|
|||
|
}),
|
|||
|
// 打包分析
|
|||
|
// visualizer({
|
|||
|
// open: true,
|
|||
|
// gzipSize: true,
|
|||
|
// brotliSize: true,
|
|||
|
// filename: 'dist/stats.html' // 分析图生成的文件名及路径
|
|||
|
// }),
|
|||
|
// 压缩
|
|||
|
viteCompression({
|
|||
|
verbose: true, // 是否在控制台输出压缩结果
|
|||
|
disable: false, // 是否禁用
|
|||
|
algorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw']
|
|||
|
ext: '.gz', // 压缩后的文件名后缀
|
|||
|
threshold: 10240, // 只有大小大于该值的资源会被处理 10240B = 10KB
|
|||
|
deleteOriginFile: false // 压缩后是否删除原文件
|
|||
|
}),
|
|||
|
// 图片压缩
|
|||
|
// viteImagemin({
|
|||
|
// verbose: true, // 是否在控制台输出压缩结果
|
|||
|
// // 图片压缩配置
|
|||
|
// // GIF 图片压缩配置
|
|||
|
// gifsicle: {
|
|||
|
// optimizationLevel: 4, // 优化级别 1-7,7为最高级别压缩
|
|||
|
// interlaced: false // 是否隔行扫描
|
|||
|
// },
|
|||
|
// // PNG 图片压缩配置
|
|||
|
// optipng: {
|
|||
|
// optimizationLevel: 4 // 优化级别 0-7,7为最高级别压缩
|
|||
|
// },
|
|||
|
// // JPEG 图片压缩配置
|
|||
|
// mozjpeg: {
|
|||
|
// quality: 60 // 压缩质量 0-100,值越小压缩率越高
|
|||
|
// },
|
|||
|
// // PNG 图片压缩配置(另一个压缩器)
|
|||
|
// pngquant: {
|
|||
|
// quality: [0.8, 0.9], // 压缩质量范围 0-1
|
|||
|
// speed: 4 // 压缩速度 1-11,值越大压缩速度越快,但质量可能会下降
|
|||
|
// },
|
|||
|
// // SVG 图片压缩配置
|
|||
|
// svgo: {
|
|||
|
// plugins: [
|
|||
|
// {
|
|||
|
// name: 'removeViewBox' // 移除 viewBox 属性
|
|||
|
// },
|
|||
|
// {
|
|||
|
// name: 'removeEmptyAttrs', // 移除空属性
|
|||
|
// active: false // 是否启用此插件
|
|||
|
// }
|
|||
|
// ]
|
|||
|
// }
|
|||
|
// })
|
|||
|
vueDevTools()
|
|||
|
],
|
|||
|
// 预加载项目必需的组件
|
|||
|
optimizeDeps: {
|
|||
|
include: [
|
|||
|
'vue',
|
|||
|
'vue-router',
|
|||
|
'pinia',
|
|||
|
'axios',
|
|||
|
'@vueuse/core',
|
|||
|
'echarts',
|
|||
|
'@wangeditor/editor',
|
|||
|
'@wangeditor/editor-for-vue',
|
|||
|
'vue-i18n',
|
|||
|
'element-plus/es/components/form/style/css',
|
|||
|
'element-plus/es/components/form-item/style/css',
|
|||
|
'element-plus/es/components/button/style/css',
|
|||
|
'element-plus/es/components/input/style/css',
|
|||
|
'element-plus/es/components/input-number/style/css',
|
|||
|
'element-plus/es/components/switch/style/css',
|
|||
|
'element-plus/es/components/upload/style/css',
|
|||
|
'element-plus/es/components/menu/style/css',
|
|||
|
'element-plus/es/components/col/style/css',
|
|||
|
'element-plus/es/components/icon/style/css',
|
|||
|
'element-plus/es/components/row/style/css',
|
|||
|
'element-plus/es/components/tag/style/css',
|
|||
|
'element-plus/es/components/dialog/style/css',
|
|||
|
'element-plus/es/components/loading/style/css',
|
|||
|
'element-plus/es/components/radio/style/css',
|
|||
|
'element-plus/es/components/radio-group/style/css',
|
|||
|
'element-plus/es/components/popover/style/css',
|
|||
|
'element-plus/es/components/scrollbar/style/css',
|
|||
|
'element-plus/es/components/tooltip/style/css',
|
|||
|
'element-plus/es/components/dropdown/style/css',
|
|||
|
'element-plus/es/components/dropdown-menu/style/css',
|
|||
|
'element-plus/es/components/dropdown-item/style/css',
|
|||
|
'element-plus/es/components/sub-menu/style/css',
|
|||
|
'element-plus/es/components/menu-item/style/css',
|
|||
|
'element-plus/es/components/divider/style/css',
|
|||
|
'element-plus/es/components/card/style/css',
|
|||
|
'element-plus/es/components/link/style/css',
|
|||
|
'element-plus/es/components/breadcrumb/style/css',
|
|||
|
'element-plus/es/components/breadcrumb-item/style/css',
|
|||
|
'element-plus/es/components/table/style/css',
|
|||
|
'element-plus/es/components/tree-select/style/css',
|
|||
|
'element-plus/es/components/table-column/style/css',
|
|||
|
'element-plus/es/components/select/style/css',
|
|||
|
'element-plus/es/components/option/style/css',
|
|||
|
'element-plus/es/components/pagination/style/css',
|
|||
|
'element-plus/es/components/tree/style/css',
|
|||
|
'element-plus/es/components/alert/style/css',
|
|||
|
'element-plus/es/components/radio-button/style/css',
|
|||
|
'element-plus/es/components/checkbox-group/style/css',
|
|||
|
'element-plus/es/components/checkbox/style/css',
|
|||
|
'element-plus/es/components/tabs/style/css',
|
|||
|
'element-plus/es/components/tab-pane/style/css',
|
|||
|
'element-plus/es/components/rate/style/css',
|
|||
|
'element-plus/es/components/date-picker/style/css',
|
|||
|
'element-plus/es/components/notification/style/css',
|
|||
|
'element-plus/es/components/image/style/css',
|
|||
|
'element-plus/es/components/statistic/style/css',
|
|||
|
'element-plus/es/components/watermark/style/css',
|
|||
|
'element-plus/es/components/config-provider/style/css',
|
|||
|
'element-plus/es/components/text/style/css',
|
|||
|
'element-plus/es/components/drawer/style/css',
|
|||
|
'element-plus/es/components/color-picker/style/css',
|
|||
|
'element-plus/es/components/backtop/style/css',
|
|||
|
'element-plus/es/components/message-box/style/css',
|
|||
|
'element-plus/es/components/skeleton/style/css',
|
|||
|
'element-plus/es/components/skeleton/style/css',
|
|||
|
'element-plus/es/components/skeleton-item/style/css',
|
|||
|
'element-plus/es/components/badge/style/css',
|
|||
|
'element-plus/es/components/steps/style/css',
|
|||
|
'element-plus/es/components/step/style/css',
|
|||
|
'element-plus/es/components/avatar/style/css',
|
|||
|
'element-plus/es/components/descriptions/style/css',
|
|||
|
'element-plus/es/components/descriptions-item/style/css',
|
|||
|
'element-plus/es/components/checkbox-group/style/css',
|
|||
|
'element-plus/es/components/progress/style/css',
|
|||
|
'element-plus/es/components/image-viewer/style/css',
|
|||
|
'element-plus/es/components/empty/style/css',
|
|||
|
'element-plus/es/components/segmented/style/css',
|
|||
|
'element-plus/es/components/calendar/style/css',
|
|||
|
'element-plus/es/components/message/style/css',
|
|||
|
'xlsx',
|
|||
|
'file-saver',
|
|||
|
'element-plus/es/components/timeline/style/css',
|
|||
|
'element-plus/es/components/timeline-item/style/css',
|
|||
|
'vue-img-cutter'
|
|||
|
]
|
|||
|
},
|
|||
|
css: {
|
|||
|
preprocessorOptions: {
|
|||
|
// sass variable and mixin
|
|||
|
scss: {
|
|||
|
api: 'modern-compiler',
|
|||
|
additionalData: `
|
|||
|
@use "@styles/variables.scss" as *; @use "@styles/mixin.scss" as *;
|
|||
|
`
|
|||
|
}
|
|||
|
},
|
|||
|
postcss: {
|
|||
|
plugins: [
|
|||
|
{
|
|||
|
postcssPlugin: 'internal:charset-removal',
|
|||
|
AtRule: {
|
|||
|
charset: (atRule) => {
|
|||
|
if (atRule.name === 'charset') {
|
|||
|
atRule.remove()
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function resolvePath(paths) {
|
|||
|
return path.resolve(__dirname, paths)
|
|||
|
}
|