/** * Vite 构建配置文件 * * 核心职责: * 1. Element Plus 按需加载 — 通过 unplugin-vue-components 自动解析组件,无需手动 import * 2. 分包策略 — 将 node_modules 拆分为独立 chunk,区分基础组件与后台组件 * 3. 首屏优化 — 去除 Element Plus modulepreload 标签,避免登录页加载后台 JS/CSS * * 分包设计: * - echarts: 单独打包,仪表盘页按需加载 * - vue-vendor: Vue/Router/Pinia 核心框架,长期缓存 * - el-admin: 后台管理页的 Element Plus 组件,进后台后一次性加载 * - 基础组件(button/input/icon等): 不单独分包,保持独立小 chunk,供 login/select 页面按需加载 */ import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' // login/select 页面用到的 Element Plus 基础组件,保持独立不打包进 el-admin // 这些组件体积小、首屏即用,独立分包可避免登录页下载后台才用的 JS const EL_BASE = [ 'button', 'input', 'form', 'form-item', 'icon', 'avatar', 'empty', 'message', 'notification', 'loading', 'popper', 'tooltip', 'overlay', 'config-provider', 'scrollbar', 'focus-trap', 'collection', ] export default defineConfig({ plugins: [ vue(), Components({ resolvers: [ElementPlusResolver({ importStyle: 'css' })], dts: 'src/types/components.d.ts', }), // 去掉 Element Plus 预加载:登录/选系统页不预下载后台才用的 JS/CSS // 原理:Vite 默认会对所有动态 import 的模块生成 标签 // Element Plus 按需加载时也会被预加载,导致首屏下载大量无用 JS // 本插件在构建 HTML 时去除这些标签,让组件在真正使用时才加载 { name: 'strip-el-preloads', transformIndexHtml(html) { // 去掉所有 modulepreload(Element Plus 组件全部按需加载) html = html.replace(/]*>/g, '') // 去掉 el-admin CSS(后台组件样式,login/select 不需要) html = html.replace(/]*el-admin[^>]*>/g, '') return html }, }, ], resolve: { alias: { '@': path.resolve(__dirname, 'src'), }, }, server: { port: 31001, }, build: { target: 'es2015', cssTarget: 'chrome61', rollupOptions: { output: { manualChunks(id) { // ECharts 体积大(~1MB),独立分包,仅在仪表盘页面才动态加载 if (id.includes('node_modules/echarts')) return 'echarts' // Vue 核心框架长期不变,独立分包以获得最佳缓存命中率 if (id.includes('node_modules/vue') || id.includes('node_modules/vue-router') || id.includes('node_modules/pinia')) return 'vue-vendor' if (id.includes('node_modules/element-plus')) { // 基础组件保持独立小 chunk(login/select 页面按需加载),不打包进 el-admin if (EL_BASE.some(c => id.includes(`/${c}/`) || id.includes(`/${c}.`) || id.endsWith(`/${c}`))) return // 管理后台组件打成一个 el-admin chunk,进后台一次性加载,减少后续页面切换的网络请求 return 'el-admin' } }, }, }, }, })