d584b578f1
- 改用 mime 标准库替代硬编码 MIME 类型(更优雅) - 全局 gzip 中间件替代手动压缩(覆盖所有响应) - ECharts 改为动态 import,首屏不再加载 1.1MB - manualChunks 拆分 vue-vendor/ui-vendor 减小主包 - 首屏 gzip 体积从 544KB 降至 236KB(减少 57%)
139 lines
4.2 KiB
TypeScript
139 lines
4.2 KiB
TypeScript
import type { Plugin } from 'vite'
|
|
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import vue from '@vitejs/plugin-vue'
|
|
import vueJsx from '@vitejs/plugin-vue-jsx'
|
|
import process from 'node:process'
|
|
import { fileURLToPath, URL } from 'node:url'
|
|
import { visualizer } from 'rollup-plugin-visualizer'
|
|
import AutoImport from 'unplugin-auto-import/vite'
|
|
import Component from 'unplugin-vue-components/vite'
|
|
import { defineConfig } from 'vite'
|
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
|
import Layouts from 'vite-plugin-vue-layouts'
|
|
import { VueRouterAutoImports } from 'vue-router/unplugin'
|
|
import VueRouter from 'vue-router/vite'
|
|
|
|
const RouteGenerateExclude = ['**/components/**', '**/layouts/**', '**/data/**', '**/types/**']
|
|
|
|
function siteConfigPlugin(): Plugin {
|
|
return {
|
|
name: 'vite-plugin-site-config',
|
|
enforce: 'pre',
|
|
transformIndexHtml: {
|
|
order: 'pre',
|
|
handler: async (html) => {
|
|
const apiBase = process.env.VITE_API_BASE || 'http://localhost:8080'
|
|
let settings: Record<string, string> = {}
|
|
|
|
try {
|
|
const response = await fetch(`${apiBase}/api/v1/settings`)
|
|
const data = await response.json() as { code?: number, data?: { basic?: { siteName?: string, siteDescription?: string, siteKeywords?: string, logoLight?: string, logoDark?: string, favicon?: string } } }
|
|
if (data.code === 200 && data.data && data.data.basic) {
|
|
settings = data.data.basic
|
|
}
|
|
}
|
|
catch {
|
|
console.log('Failed to fetch site settings, using defaults')
|
|
}
|
|
|
|
const siteName = settings.siteName || '微授权'
|
|
const siteDescription = settings.siteDescription || '专业的应用验证平台'
|
|
const siteKeywords = settings.siteKeywords || '验证平台,软件授权,卡密验证'
|
|
const logoLight = settings.logoLight || ''
|
|
const logoDark = settings.logoDark || ''
|
|
const favicon = settings.favicon || ''
|
|
|
|
html = html.replace(/\{\{\.SiteName\}\}/g, siteName)
|
|
html = html.replace(/\{\{\.SiteDescription\}\}/g, siteDescription)
|
|
html = html.replace(/\{\{\.SiteKeywords\}\}/g, siteKeywords)
|
|
html = html.replace(/\{\{\.LogoLight\}\}/g, logoLight)
|
|
html = html.replace(/\{\{\.LogoDark\}\}/g, logoDark)
|
|
html = html.replace(/\{\{\.Favicon\}\}/g, favicon)
|
|
|
|
return html
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
siteConfigPlugin(),
|
|
VueRouter({
|
|
exclude: RouteGenerateExclude,
|
|
dts: 'src/types/route-map.d.ts',
|
|
}),
|
|
vue(),
|
|
vueJsx(),
|
|
vueDevTools(),
|
|
tailwindcss(),
|
|
visualizer({ gzipSize: true, brotliSize: true }),
|
|
Layouts({
|
|
defaultLayout: 'default',
|
|
}),
|
|
AutoImport({
|
|
include: [
|
|
/\.[tj]sx?$/,
|
|
/\.vue$/,
|
|
],
|
|
imports: [
|
|
'vue',
|
|
VueRouterAutoImports,
|
|
],
|
|
dirs: [
|
|
'src/composables/**/*.ts',
|
|
'src/constants/**/*.ts',
|
|
'src/stores/**/*.ts',
|
|
],
|
|
defaultExportByFilename: true,
|
|
dts: 'src/types/auto-import.d.ts',
|
|
}),
|
|
Component({
|
|
dirs: [
|
|
'src/components',
|
|
],
|
|
collapseSamePrefixes: true,
|
|
directoryAsNamespace: true,
|
|
dts: 'src/types/auto-import-components.d.ts',
|
|
}),
|
|
],
|
|
resolve: {
|
|
alias: {
|
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
},
|
|
},
|
|
build: {
|
|
rollupOptions: {
|
|
output: {
|
|
chunkFileNames: (chunkInfo) => {
|
|
const name = chunkInfo.name?.replace(/^_+/, '') || 'chunk'
|
|
return `assets/${name}-[hash].js`
|
|
},
|
|
entryFileNames: 'assets/[name]-[hash].js',
|
|
assetFileNames: 'assets/[name]-[hash].[ext]',
|
|
manualChunks: {
|
|
'vue-vendor': ['vue', 'vue-router', 'vue-i18n', 'pinia', '@vueuse/core'],
|
|
'ui-vendor': ['reka-ui', 'class-variance-authority', 'clsx', 'tailwind-merge', 'lucide-vue-next'],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
server: {
|
|
proxy: {
|
|
'/api': {
|
|
target: 'http://localhost:8080',
|
|
changeOrigin: true,
|
|
},
|
|
'/uploads': {
|
|
target: 'http://localhost:8080',
|
|
changeOrigin: true,
|
|
},
|
|
},
|
|
},
|
|
esbuild: {
|
|
drop: ['debugger'],
|
|
pure: ['console.log'],
|
|
},
|
|
})
|