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 = {} 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(id) { if (id.includes('node_modules/echarts/') || id.includes('node_modules\\echarts\\')) { return 'echarts' } if (id.includes('node_modules/chart.js/') || id.includes('node_modules\\chart.js\\')) { return 'chart' } if (id.includes('node_modules/vue/') || id.includes('node_modules/vue-router/') || id.includes('node_modules/vue-i18n/') || id.includes('node_modules/pinia/') || id.includes('node_modules/@vueuse/')) { return 'vue-vendor' } if (id.includes('node_modules/reka-ui/') || id.includes('node_modules/class-variance-authority/') || id.includes('node_modules/clsx/') || id.includes('node_modules/tailwind-merge/') || id.includes('node_modules/lucide-vue-next/')) { return 'ui-vendor' } if (id.includes('node_modules/vee-validate/') || id.includes('node_modules/@vee-validate/') || id.includes('node_modules/zod/')) { return 'form-vendor' } if (id.includes('node_modules/@tanstack/')) { return 'table-vendor' } }, }, }, }, server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, }, '/uploads': { target: 'http://localhost:8080', changeOrigin: true, }, }, }, esbuild: { drop: ['debugger'], pure: ['console.log'], }, optimizeDeps: { exclude: ['echarts', 'chart.js'], }, })