import { fileURLToPath, URL } from 'node:url' import { defineConfig, loadEnv } from 'vite' import vue from '@vitejs/plugin-vue' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), '') const allowedHosts = parseAllowedHosts(env.VITE_ALLOWED_HOSTS) return { plugins: [ vue(), AutoImport({ imports: ['vue', 'vue-router'], dts: 'src/auto-imports.d.ts', resolvers: [ElementPlusResolver({ importStyle: 'css' })], }), Components({ dts: 'src/components.d.ts', resolvers: [ElementPlusResolver({ importStyle: 'css' })], }), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, server: { host: env.VITE_DEV_HOST === 'true', allowedHosts: env.VITE_ALLOW_ALL_HOSTS === 'true' ? true : allowedHosts, proxy: { '/api': { target: env.VITE_API_TARGET || 'http://localhost:3000', changeOrigin: true, }, }, }, build: { rollupOptions: { output: { manualChunks: splitVendorChunk, }, }, }, } }) function parseAllowedHosts(value?: string) { const hosts = value ?.split(',') .map((host) => host.trim()) .filter(Boolean) return hosts && hosts.length > 0 ? hosts : ['localhost', '127.0.0.1'] } const elementPlusChunkGroups: Array<[string, string[]]> = [ [ 'element-plus-form', [ '/components/form', '/components/input', '/components/select', '/components/date-picker', '/components/checkbox', '/components/radio', '/components/switch', '/components/upload', ], ], [ 'element-plus-data', [ '/components/table', '/components/pagination', '/components/tag', '/components/card', '/components/descriptions', '/components/empty', ], ], [ 'element-plus-feedback', [ '/components/message', '/components/message-box', '/components/dialog', '/components/popover', '/components/tooltip', '/components/loading', ], ], [ 'element-plus-navigation', ['/components/menu', '/components/tabs', '/components/breadcrumb', '/components/dropdown'], ], [ 'element-plus-layout', [ '/components/container', '/components/row', '/components/col', '/components/space', '/components/divider', ], ], ] function splitVendorChunk(id: string) { if (!id.includes('/node_modules/')) { return } if (id.includes('/node_modules/@element-plus/icons-vue/')) { return 'element-plus-icons' } if (id.includes('/node_modules/element-plus/')) { return splitElementPlusChunk(id) } if (id.includes('/node_modules/vue/') || id.includes('/node_modules/vue-router/')) { return 'vue-vendor' } if (id.includes('/node_modules/axios/')) { return 'axios' } if (id.includes('/node_modules/qrcode/')) { return 'qrcode' } return 'vendor' } function splitElementPlusChunk(id: string) { for (const [chunkName, includesList] of elementPlusChunkGroups) { if (includesList.some((includePath) => id.includes(includePath))) { return chunkName } } return 'element-plus-core' }