Vite 5作为前端工程化构建工具,开发环境基于ESM按需编译实现毫秒级热更新,生产环境基于Rollup打包输出优化后的静态资源。Vite 5相比v4在Rollup 4升级、CSS代码分割、JSON模块导入等方面均有改进。前端开发中,合理的Vite配置对打包体积、首屏加载速度和构建效率有直接影响。本文从构建配置到生产优化,覆盖Vite 5打包优化的关键环节。
Vite 5 Rollup构建配置与代码分割策略
Vite生产构建默认使用Rollup,通过vite.config.ts的build.rollupOptions进行配置。代码分割(Code Splitting)是打包优化的第一步,将vendor代码与业务代码分离,利用浏览器缓存减少重复下载。
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
build: {
outDir: 'dist',
sourcemap: 'hidden',
chunkSizeWarningLimit: 500,
assetsInlineLimit: 4096,
cssCodeSplit: true,
minify: 'esbuild',
rollupOptions: {
output: {
entryFileNames: 'js/[name]-[hash].js',
chunkFileNames: 'js/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash].[ext]',
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor'
}
if (id.includes('react-router')) {
return 'router-vendor'
}
if (id.includes('antd') || id.includes('@ant-design')) {
return 'ui-vendor'
}
if (id.includes('lodash') || id.includes('dayjs')) {
return 'utils-vendor'
}
return 'vendor'
}
}
}
}
}
})
manualChunks函数按模块路径将依赖分配到不同chunk。React运行时变动频率低,单独打包后可长期缓存;UI组件库体积较大但更新不频繁,独立chunk避免每次发布都重新下载。
生产环境打包体积分析与Tree Shaking优化
打包体积分析是优化的前提。rollup-plugin-visualizer生成交互式Treemap,直观展示每个模块的体积占比。配合Vite的build.reportCompressedSize查看gzip压缩后大小。
// 安装分析插件
// npm i -D rollup-plugin-visualizer
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
react(),
visualizer({
filename: 'stats.html',
template: 'treemap',
gzipSize: true,
brotliSize: true,
open: false
})
],
build: {
reportCompressedSize: true
}
})
// 分析命令
// npx vite build --mode production
// 打开 stats.html 查看体积分布
Tree Shaking依赖ES模块的静态分析能力。确保package.json中sideEffects字段正确声明,让Rollup安全移除未使用的导出:
// package.json
{
"name": "my-app",
"sideEffects": [
"*.css",
"*.scss",
"*.less",
"./src/polyfills.js"
]
}
// sideEffects: false 表示所有模块无副作用
// 但有CSS导入时需声明CSS文件有副作用
Lodash是Tree Shaking失效的典型案例。import { debounce } from 'lodash'会引入整个Lodash库(70KB+),而import debounce from 'lodash/debounce'只引入debounce函数(2KB)。使用lodash-es或babel-plugin-lodash可自动优化导入路径:
// 错误:导入整个lodash
import { debounce, throttle } from 'lodash' // 70KB+
// 正确:按路径导入
import debounce from 'lodash/debounce' // 2KB
import throttle from 'lodash/throttle' // 1KB
// 最佳:使用lodash-es(ESM格式,支持Tree Shaking)
import { debounce, throttle } from 'lodash-es' // 仅打包使用的函数
按需加载与动态导入路由懒加载
路由级懒加载通过动态import()实现,将每个路由页面拆分为独立chunk,首屏只加载当前路由代码。React和Vue均原生支持动态导入。
// React Router懒加载
import { lazy, Suspense } from 'react'
import { Routes, Route } from 'react-router-dom'
// 动态导入:每个页面生成独立chunk
const Home = lazy(() => import('@/pages/Home'))
const Dashboard = lazy(() => import('@/pages/Dashboard'))
const Settings = lazy(() =>
import('@/pages/Settings').then(m => ({ default: m.Settings }))
)
function App() {
return (
<Suspense fallback={<div>加载中...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
)
}
// 预加载策略:鼠标悬停时预加载chunk
const prefetchRoute = (importFn) => {
let loaded = false
const lazyComp = lazy(() => {
loaded = true
return importFn()
})
lazyComp.prefetch = () => {
if (!loaded) importFn()
}
return lazyComp
}
对于大型组件(如富文本编辑器、图表库),可使用vite-plugin-dynamic-import实现更细粒度的按需加载。配合React 18的startTransition将懒加载标记为低优先级过渡,避免阻塞用户交互。
静态资源处理与CDN部署配置
图片资源优化对首屏加载影响显著。Vite 5支持通过vite-plugin-imagemin压缩图片,vite-plugin-svg-sprite将SVG图标合并为sprite:
// vite.config.ts
import { imageminPlugin } from 'vite-plugin-imagemin'
import { viteSvgSpritesPlugin } from 'vite-plugin-svg-sprite'
export default defineConfig({
plugins: [
imageminPlugin({
gifsicle: { optimizationLevel: 7 },
mozjpeg: { quality: 80 },
pngquant: { quality: [0.65, 0.8] },
webp: { quality: 80 }
}),
viteSvgSpritesPlugin({
symbolId: 'icon-[name]'
})
]
})
// CDN外部化:大型依赖通过CDN加载,不打包进bundle
export default defineConfig({
build: {
rollupOptions: {
external: {
react: 'React',
'react-dom': 'ReactDOM',
'react-router-dom': 'ReactRouterDOM'
},
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'react-router-dom': 'ReactRouterDOM'
}
}
}
}
})
// index.html 引入CDN
// <script src="https://cdn.example.com/react@18.3.1/react.production.min.js"></script>
gzip/brotli预压缩可进一步减少传输体积。Vite构建时通过vite-plugin-compression生成.gz和.br文件,Nginx直接返回预压缩文件:
// vite.config.ts
import viteCompression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
viteCompression({
algorithm: 'gzip',
ext: '.gz',
threshold: 10240 // 10KB以上才压缩
}),
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
threshold: 10240
})
]
})
// Nginx配置:优先返回预压缩文件
// gzip_static on;
// brotli_static on;
Vite 5的前端工程化能力已覆盖构建优化的大部分场景。实际项目中,建议建立打包体积预算(budget),在CI/CD流水线中通过vite build输出JSON分析报告,当chunk超过预算时阻断构建发布,从流程层面保证前端性能持续达标。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/vite5-gou-jian-gong-ju-shen-du-pei-zhi-yu-sheng-chan-huan/