perf(build): 将生产构建从约 41.6s 优化到约 21.6s

- 使用 oxc 替换 terser 作为生产压缩器
- 生产构建跳过 ESLint、progress 和 auto d.ts 生成
- gzip/brotli 产物改为通过 VITE_COMPRESS 按需生成
- 移除无用的 EJS 和 top-level-await 构建插件
- 删除 vite-plugin-top-level-await 依赖
master-bpm-bug-fix
YunaiV 2026-06-20 04:31:53 -07:00
parent fb94d37f5f
commit 3d37515cfc
7 changed files with 40 additions and 203 deletions

View File

@ -21,6 +21,9 @@ VITE_DROP_CONSOLE=false
# 是否sourcemap
VITE_SOURCEMAP=true
# 是否开启压缩,可以设置为 none, gzip, brotli, gzip,brotli
VITE_COMPRESS=none
# 打包路径
VITE_BASE_PATH=/
@ -34,4 +37,4 @@ VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
VITE_APP_CAPTCHA_ENABLE=true
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
VITE_GOVIEW_URL='http://127.0.0.1:3000'

View File

@ -21,6 +21,9 @@ VITE_DROP_CONSOLE=false
# 是否sourcemap
VITE_SOURCEMAP=false
# 是否开启压缩,可以设置为 none, gzip, brotli, gzip,brotli
VITE_COMPRESS=none
# 打包路径
VITE_BASE_PATH=/
@ -31,4 +34,4 @@ VITE_MALL_H5_DOMAIN='http://localhost:3000'
VITE_APP_CAPTCHA_ENABLE=false
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
VITE_GOVIEW_URL='http://127.0.0.1:3000'

View File

@ -21,6 +21,9 @@ VITE_DROP_CONSOLE=true
# 是否sourcemap
VITE_SOURCEMAP=false
# 是否开启压缩,可以设置为 none, gzip, brotli, gzip,brotli
VITE_COMPRESS=none
# 打包路径
VITE_BASE_PATH=/
@ -31,4 +34,4 @@ VITE_OUT_DIR=dist-prod
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
VITE_GOVIEW_URL='http://127.0.0.1:3000'

View File

@ -3,30 +3,32 @@ import Vue from '@vitejs/plugin-vue'
import VueJsx from '@vitejs/plugin-vue-jsx'
import progress from 'vite-plugin-progress'
import EslintPlugin from 'vite-plugin-eslint2'
import { ViteEjsPlugin } from 'vite-plugin-ejs'
// @ts-ignore
import ElementPlus from 'unplugin-element-plus/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import viteCompression from 'vite-plugin-compression'
import topLevelAwait from 'vite-plugin-top-level-await'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons-ng'
import UnoCSS from 'unocss/vite'
export function createVitePlugins() {
export function createVitePlugins(isBuild = false, env: Record<string, string> = {}) {
const root = process.cwd()
const compressTypes = (env.VITE_COMPRESS || '')
.split(',')
.map((item) => item.trim())
.filter((item) => item === 'gzip' || item === 'brotli')
// 路径查找
function pathResolve(dir: string) {
return resolve(root, '.', dir)
}
return [
const plugins = [
Vue(),
VueJsx(),
UnoCSS(),
progress(),
!isBuild && progress(),
ElementPlus({}),
AutoImport({
include: [
@ -48,7 +50,7 @@ export function createVitePlugins() {
'@/utils/dict': ['DICT_TYPE']
}
],
dts: 'src/types/auto-imports.d.ts',
dts: !isBuild && 'src/types/auto-imports.d.ts',
resolvers: [ElementPlusResolver()],
eslintrc: {
enabled: false, // Default `false`
@ -58,12 +60,12 @@ export function createVitePlugins() {
}),
Components({
// 生成自定义 `auto-components.d.ts` 全局声明
dts: 'src/types/auto-components.d.ts',
dts: !isBuild && 'src/types/auto-components.d.ts',
// 自定义组件的解析器
resolvers: [ElementPlusResolver()],
globs: ['src/components/**/**.{vue, md}', '!src/components/DiyEditor/components/mobile/**']
}),
EslintPlugin({
!isBuild && EslintPlugin({
cache: false,
include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件
}),
@ -72,7 +74,7 @@ export function createVitePlugins() {
iconDirs: [pathResolve('src/assets/svgs')],
symbolId: 'icon-[dir]-[name]'
}),
viteCompression({
isBuild && compressTypes.includes('gzip') && viteCompression({
verbose: true, // 是否在控制台输出压缩结果
disable: false, // 是否禁用
threshold: 10240, // 体积大于 threshold 才会被压缩,单位 b
@ -80,13 +82,15 @@ export function createVitePlugins() {
ext: '.gz', // 生成的压缩包后缀
deleteOriginFile: false //压缩后是否删除源文件
}),
ViteEjsPlugin(),
topLevelAwait({
// https://juejin.cn/post/7152191742513512485
// The export name of top-level await promise for each chunk module
promiseExportName: '__tla',
// The function to generate import names of top-level await promise in each chunk module
promiseImportName: (i) => `__tla_${i}`
isBuild && compressTypes.includes('brotli') && viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'brotliCompress',
ext: '.br',
deleteOriginFile: false
})
]
return plugins.filter(Boolean)
}

View File

@ -135,7 +135,6 @@
"vite-plugin-eslint2": "^5.1.0",
"vite-plugin-progress": "^0.0.7",
"vite-plugin-svg-icons-ng": "^1.9.0",
"vite-plugin-top-level-await": "^1.6.0",
"vue-eslint-parser": "^10.4.0",
"vue-tsc": "^3.2.8"
},

View File

@ -333,9 +333,6 @@ importers:
vite-plugin-svg-icons-ng:
specifier: ^1.9.0
version: 1.9.0(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4))
vite-plugin-top-level-await:
specifier: ^1.6.0
version: 1.6.0(rollup@4.60.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4))
vue-eslint-parser:
specifier: ^10.4.0
version: 10.4.0(eslint@10.3.0(jiti@2.6.1))
@ -1864,15 +1861,6 @@ packages:
'@rolldown/pluginutils@1.0.0-rc.17':
resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==}
'@rollup/plugin-virtual@3.0.2':
resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
'@rollup/pluginutils@5.3.0':
resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
engines: {node: '>=14.0.0'}
@ -2038,88 +2026,6 @@ packages:
'@sphinxxxx/color-conversion@2.2.2':
resolution: {integrity: sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==}
'@swc/core-darwin-arm64@1.15.18':
resolution: {integrity: sha512-+mIv7uBuSaywN3C9LNuWaX1jJJ3SKfiJuE6Lr3bd+/1Iv8oMU7oLBjYMluX1UrEPzwN2qCdY6Io0yVicABoCwQ==, tarball: https://registry.npmmirror.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
'@swc/core-darwin-x64@1.15.18':
resolution: {integrity: sha512-wZle0eaQhnzxWX5V/2kEOI6Z9vl/lTFEC6V4EWcn+5pDjhemCpQv9e/TDJ0GIoiClX8EDWRvuZwh+Z3dhL1NAg==, tarball: https://registry.npmmirror.com/@swc/core-darwin-x64/-/core-darwin-x64-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
'@swc/core-linux-arm-gnueabihf@1.15.18':
resolution: {integrity: sha512-ao61HGXVqrJFHAcPtF4/DegmwEkVCo4HApnotLU8ognfmU8x589z7+tcf3hU+qBiU1WOXV5fQX6W9Nzs6hjxDw==, tarball: https://registry.npmmirror.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
'@swc/core-linux-arm64-gnu@1.15.18':
resolution: {integrity: sha512-3xnctOBLIq3kj8PxOCgPrGjBLP/kNOddr6f5gukYt/1IZxsITQaU9TDyjeX6jG+FiCIHjCuWuffsyQDL5Ew1bg==, tarball: https://registry.npmmirror.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@swc/core-linux-arm64-musl@1.15.18':
resolution: {integrity: sha512-0a+Lix+FSSHBSBOA0XznCcHo5/1nA6oLLjcnocvzXeqtdjnPb+SvchItHI+lfeiuj1sClYPDvPMLSLyXFaiIKw==, tarball: https://registry.npmmirror.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@swc/core-linux-x64-gnu@1.15.18':
resolution: {integrity: sha512-wG9J8vReUlpaHz4KOD/5UE1AUgirimU4UFT9oZmupUDEofxJKYb1mTA/DrMj0s78bkBiNI+7Fo2EgPuvOJfuAA==, tarball: https://registry.npmmirror.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@swc/core-linux-x64-musl@1.15.18':
resolution: {integrity: sha512-4nwbVvCphKzicwNWRmvD5iBaZj8JYsRGa4xOxJmOyHlMDpsvvJ2OR2cODlvWyGFH6BYL1MfIAK3qph3hp0Az6g==, tarball: https://registry.npmmirror.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@swc/core-win32-arm64-msvc@1.15.18':
resolution: {integrity: sha512-zk0RYO+LjiBCat2RTMHzAWaMky0cra9loH4oRrLKLLNuL+jarxKLFDA8xTZWEkCPLjUTwlRN7d28eDLLMgtUcQ==, tarball: https://registry.npmmirror.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
'@swc/core-win32-ia32-msvc@1.15.18':
resolution: {integrity: sha512-yVuTrZ0RccD5+PEkpcLOBAuPbYBXS6rslENvIXfvJGXSdX5QGi1ehC4BjAMl5FkKLiam4kJECUI0l7Hq7T1vwg==, tarball: https://registry.npmmirror.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
'@swc/core-win32-x64-msvc@1.15.18':
resolution: {integrity: sha512-7NRmE4hmUQNCbYU3Hn9Tz57mK9Qq4c97ZS+YlamlK6qG9Fb5g/BB3gPDe0iLlJkns/sYv2VWSkm8c3NmbEGjbg==, tarball: https://registry.npmmirror.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.18.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
'@swc/core@1.15.18':
resolution: {integrity: sha512-z87aF9GphWp//fnkRsqvtY+inMVPgYW3zSlXH1kJFvRT5H/wiAn+G32qW5l3oEk63KSF1x3Ov0BfHCObAmT8RA==}
engines: {node: '>=10'}
peerDependencies:
'@swc/helpers': '>=0.5.17'
peerDependenciesMeta:
'@swc/helpers':
optional: true
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
'@swc/types@0.1.25':
resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==}
'@swc/wasm@1.15.18':
resolution: {integrity: sha512-zeSORFArxqUwfVMTRHu8AN9k9LlfSn0CKDSzLhJDITpgLoS0xpnocxsgMjQjUcVYDgO47r9zLP49HEjH/iGsFg==}
'@sxzz/popperjs-es@2.11.8':
resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==, tarball: https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz}
@ -5462,10 +5368,6 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
uuid@10.0.0:
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
hasBin: true
vanilla-picker@2.12.3:
resolution: {integrity: sha512-qVkT1E7yMbUsB2mmJNFmaXMWE2hF8ffqzMMwe9zdAikd8u2VfnsVY2HQcOUi2F38bgbxzlJBEdS1UUhOXdF9GQ==}
@ -5523,11 +5425,6 @@ packages:
peerDependencies:
vite: '>=5.0.0'
vite-plugin-top-level-await@1.6.0:
resolution: {integrity: sha512-bNhUreLamTIkoulCR9aDXbTbhLk6n1YE8NJUTTxl5RYskNRtzOR0ASzSjBVRtNdjIfngDXo11qOsybGLNsrdww==}
peerDependencies:
vite: '>=2.8'
vite@8.0.10:
resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==}
engines: {node: ^20.19.0 || >=22.12.0}
@ -7435,10 +7332,6 @@ snapshots:
'@rolldown/pluginutils@1.0.0-rc.17': {}
'@rollup/plugin-virtual@3.0.2(rollup@4.60.3)':
optionalDependencies:
rollup: 4.60.3
'@rollup/pluginutils@5.3.0(rollup@4.60.3)':
dependencies:
'@types/estree': 1.0.8
@ -7534,60 +7427,6 @@ snapshots:
'@sphinxxxx/color-conversion@2.2.2': {}
'@swc/core-darwin-arm64@1.15.18':
optional: true
'@swc/core-darwin-x64@1.15.18':
optional: true
'@swc/core-linux-arm-gnueabihf@1.15.18':
optional: true
'@swc/core-linux-arm64-gnu@1.15.18':
optional: true
'@swc/core-linux-arm64-musl@1.15.18':
optional: true
'@swc/core-linux-x64-gnu@1.15.18':
optional: true
'@swc/core-linux-x64-musl@1.15.18':
optional: true
'@swc/core-win32-arm64-msvc@1.15.18':
optional: true
'@swc/core-win32-ia32-msvc@1.15.18':
optional: true
'@swc/core-win32-x64-msvc@1.15.18':
optional: true
'@swc/core@1.15.18':
dependencies:
'@swc/counter': 0.1.3
'@swc/types': 0.1.25
optionalDependencies:
'@swc/core-darwin-arm64': 1.15.18
'@swc/core-darwin-x64': 1.15.18
'@swc/core-linux-arm-gnueabihf': 1.15.18
'@swc/core-linux-arm64-gnu': 1.15.18
'@swc/core-linux-arm64-musl': 1.15.18
'@swc/core-linux-x64-gnu': 1.15.18
'@swc/core-linux-x64-musl': 1.15.18
'@swc/core-win32-arm64-msvc': 1.15.18
'@swc/core-win32-ia32-msvc': 1.15.18
'@swc/core-win32-x64-msvc': 1.15.18
'@swc/counter@0.1.3': {}
'@swc/types@0.1.25':
dependencies:
'@swc/counter': 0.1.3
'@swc/wasm@1.15.18': {}
'@sxzz/popperjs-es@2.11.8': {}
'@transloadit/prettier-bytes@0.0.7': {}
@ -11385,8 +11224,6 @@ snapshots:
util-deprecate@1.0.2: {}
uuid@10.0.0: {}
vanilla-picker@2.12.3:
dependencies:
'@sphinxxxx/color-conversion': 2.2.2
@ -11456,17 +11293,6 @@ snapshots:
tinyglobby: 0.2.16
vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)
vite-plugin-top-level-await@1.6.0(rollup@4.60.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)):
dependencies:
'@rollup/plugin-virtual': 3.0.2(rollup@4.60.3)
'@swc/core': 1.15.18
'@swc/wasm': 1.15.18
uuid: 10.0.0
vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)
transitivePeerDependencies:
- '@swc/helpers'
- rollup
vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4):
dependencies:
lightningcss: 1.32.0

View File

@ -46,7 +46,7 @@ export default ({command, mode}: ConfigEnv): UserConfig => {
// },
},
// 项目使用的vite插件。 单独提取到build/vite/plugin中管理
plugins: createVitePlugins(),
plugins: createVitePlugins(isBuild, env),
css: {
lightningcss: {
// Preserve legacy star-hack declarations by stripping invalid syntax during minification.
@ -80,18 +80,17 @@ export default ({command, mode}: ConfigEnv): UserConfig => {
]
},
build: {
minify: 'terser',
minify: 'oxc',
outDir: env.VITE_OUT_DIR || 'dist',
sourcemap: env.VITE_SOURCEMAP === 'true' ? 'inline' : false,
// brotliSize: false,
terserOptions: {
compress: {
drop_debugger: env.VITE_DROP_DEBUGGER === 'true',
drop_console: env.VITE_DROP_CONSOLE === 'true'
}
},
rollupOptions: {
output: {
minify: {
compress: {
dropDebugger: env.VITE_DROP_DEBUGGER === 'true',
dropConsole: env.VITE_DROP_CONSOLE === 'true'
}
},
codeSplitting: {
groups: [
{ name: 'echarts', test: /node_modules[\\/]echarts[\\/]/ }, // 将 echarts 单独打包,参考 https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues/IAB1SX 讨论