82 lines
3.4 KiB
TypeScript
82 lines
3.4 KiB
TypeScript
/**
|
||
* 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 的模块生成 <link rel="modulepreload"> 标签
|
||
// Element Plus 按需加载时也会被预加载,导致首屏下载大量无用 JS
|
||
// 本插件在构建 HTML 时去除这些标签,让组件在真正使用时才加载
|
||
{
|
||
name: 'strip-el-preloads',
|
||
transformIndexHtml(html) {
|
||
// 去掉所有 modulepreload(Element Plus 组件全部按需加载)
|
||
html = html.replace(/<link rel="modulepreload"[^>]*>/g, '')
|
||
// 去掉 el-admin CSS(后台组件样式,login/select 不需要)
|
||
html = html.replace(/<link[^>]*el-admin[^>]*>/g, '')
|
||
return html
|
||
},
|
||
},
|
||
],
|
||
resolve: {
|
||
alias: {
|
||
'@': path.resolve(__dirname, 'src'),
|
||
},
|
||
},
|
||
server: {
|
||
port: 5001,
|
||
},
|
||
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'
|
||
}
|
||
},
|
||
},
|
||
},
|
||
},
|
||
})
|