224 lines
5.5 KiB
TypeScript
224 lines
5.5 KiB
TypeScript
import { defineConfig } from 'vite'
|
|
import vue from '@vitejs/plugin-vue'
|
|
import { resolve } from 'path'
|
|
import AutoImport from 'unplugin-auto-import/vite'
|
|
import Components from 'unplugin-vue-components/vite'
|
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
|
import { VitePWA } from 'vite-plugin-pwa'
|
|
import { visualizer } from 'rollup-plugin-visualizer'
|
|
import viteCompression from 'vite-plugin-compression'
|
|
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
|
|
|
|
// https://vitejs.dev/config/
|
|
export default defineConfig(({ mode, command }) => {
|
|
const isProduction = mode === 'production'
|
|
const isAnalyze = mode === 'analyze'
|
|
|
|
return {
|
|
base: isProduction ? '/emotion-museum/' : '/',
|
|
plugins: [
|
|
vue(),
|
|
|
|
// 自动导入
|
|
AutoImport({
|
|
imports: [
|
|
'vue',
|
|
'vue-router',
|
|
'pinia',
|
|
'@vueuse/core',
|
|
{
|
|
'vue-i18n': ['useI18n']
|
|
}
|
|
],
|
|
resolvers: [ElementPlusResolver()],
|
|
dts: true,
|
|
eslintrc: {
|
|
enabled: true
|
|
}
|
|
}),
|
|
|
|
// 组件自动导入
|
|
Components({
|
|
resolvers: [ElementPlusResolver()],
|
|
dts: true
|
|
}),
|
|
|
|
// PWA支持
|
|
VitePWA({
|
|
registerType: 'autoUpdate',
|
|
includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
|
|
manifest: {
|
|
name: '情绪博物馆',
|
|
short_name: '情绪博物馆',
|
|
description: '记录情绪,分享心情的温暖空间',
|
|
theme_color: '#4A90E2',
|
|
background_color: '#ffffff',
|
|
display: 'standalone',
|
|
icons: [
|
|
{
|
|
src: 'pwa-192x192.png',
|
|
sizes: '192x192',
|
|
type: 'image/png'
|
|
},
|
|
{
|
|
src: 'pwa-512x512.png',
|
|
sizes: '512x512',
|
|
type: 'image/png'
|
|
}
|
|
]
|
|
},
|
|
workbox: {
|
|
globPatterns: ['**/*.{js,css,html,ico,png,svg}']
|
|
}
|
|
}),
|
|
|
|
// 国际化支持
|
|
VueI18nPlugin({
|
|
include: resolve(__dirname, './src/i18n/locales/**')
|
|
}),
|
|
|
|
// Gzip压缩(仅生产环境)
|
|
isProduction && viteCompression({
|
|
verbose: true,
|
|
disable: false,
|
|
threshold: 10240,
|
|
algorithm: 'gzip',
|
|
ext: '.gz'
|
|
}),
|
|
|
|
// 构建分析(仅分析模式)
|
|
isAnalyze && visualizer({
|
|
filename: 'dist/stats.html',
|
|
open: true,
|
|
gzipSize: true,
|
|
brotliSize: true
|
|
})
|
|
].filter(Boolean),
|
|
|
|
resolve: {
|
|
alias: {
|
|
'@': resolve(__dirname, 'src'),
|
|
'~': resolve(__dirname, 'src')
|
|
}
|
|
},
|
|
|
|
define: {
|
|
global: 'globalThis',
|
|
__VUE_I18N_FULL_INSTALL__: true,
|
|
__VUE_I18N_LEGACY_API__: false,
|
|
__INTLIFY_PROD_DEVTOOLS__: false
|
|
},
|
|
|
|
server: {
|
|
port: 5173,
|
|
open: true,
|
|
proxy: {
|
|
'/api': {
|
|
target: 'http://localhost:19089',
|
|
changeOrigin: true,
|
|
secure: false
|
|
},
|
|
'/ws': {
|
|
target: 'ws://localhost:19089',
|
|
ws: true,
|
|
changeOrigin: true
|
|
}
|
|
}
|
|
},
|
|
|
|
build: {
|
|
outDir: 'dist',
|
|
sourcemap: !isProduction,
|
|
minify: isProduction ? 'terser' : false,
|
|
terserOptions: isProduction ? {
|
|
compress: {
|
|
drop_console: true,
|
|
drop_debugger: true,
|
|
pure_funcs: ['console.log', 'console.info', 'console.debug']
|
|
},
|
|
mangle: {
|
|
safari10: true
|
|
}
|
|
} : {},
|
|
rollupOptions: {
|
|
external: (id) => {
|
|
if (id.includes('echarts') && id.includes('extension')) {
|
|
return true
|
|
}
|
|
return false
|
|
},
|
|
output: {
|
|
chunkFileNames: 'js/[name]-[hash].js',
|
|
entryFileNames: 'js/[name]-[hash].js',
|
|
assetFileNames: (assetInfo) => {
|
|
const fileName = assetInfo.name || 'asset'
|
|
const info = fileName.split('.')
|
|
const ext = info[info.length - 1]
|
|
if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)$/.test(fileName)) {
|
|
return `media/[name]-[hash].${ext}`
|
|
}
|
|
if (/\.(png|jpe?g|gif|svg|webp|ico)$/.test(fileName)) {
|
|
return `images/[name]-[hash].${ext}`
|
|
}
|
|
if (/\.(woff2?|eot|ttf|otf)$/.test(fileName)) {
|
|
return `fonts/[name]-[hash].${ext}`
|
|
}
|
|
return `assets/[name]-[hash].${ext}`
|
|
},
|
|
manualChunks: (id) => {
|
|
// 第三方库分包
|
|
if (id.includes('node_modules')) {
|
|
if (id.includes('vue') || id.includes('pinia') || id.includes('vue-router')) {
|
|
return 'vue-vendor'
|
|
}
|
|
if (id.includes('element-plus')) {
|
|
return 'element-plus'
|
|
}
|
|
if (id.includes('echarts')) {
|
|
return 'echarts'
|
|
}
|
|
if (id.includes('lodash') || id.includes('dayjs') || id.includes('axios')) {
|
|
return 'utils'
|
|
}
|
|
return 'vendor'
|
|
}
|
|
|
|
// 业务模块分包
|
|
if (id.includes('/src/views/')) {
|
|
const pathSegments = id.split('/src/views/')[1].split('/')
|
|
if (pathSegments.length > 1) {
|
|
return `pages-${pathSegments[0]}`
|
|
}
|
|
}
|
|
|
|
if (id.includes('/src/components/')) {
|
|
return 'components'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// 构建性能优化
|
|
chunkSizeWarningLimit: 1000,
|
|
reportCompressedSize: !isProduction,
|
|
|
|
// 目标浏览器
|
|
target: ['es2015', 'chrome63', 'firefox67', 'safari12']
|
|
},
|
|
|
|
optimizeDeps: {
|
|
include: [
|
|
'vue',
|
|
'vue-router',
|
|
'pinia',
|
|
'element-plus',
|
|
'echarts',
|
|
'vue-echarts',
|
|
'@vueuse/core',
|
|
'dayjs',
|
|
'lodash-es'
|
|
]
|
|
}
|
|
}
|
|
})
|