Vite 基于 Rollup 的插件机制,并结合自身开发服务器特性,提供了强大的扩展能力。合理利用插件体系和构建配置,能够显著优化项目的加载性能和打包体积。
插件体系
Vite 插件沿用了 Rollup 的插件接口,同时扩展了一些 Vite 特有的钩子(如 configureServer)。一个 Vite 插件本质上是一个对象,包含名称和一组钩子函数,可以在构建过程的各个阶段执行自定义逻辑。
常用插件推荐
@vitejs/plugin-react:提供 React Fast Refresh、JSX 转换等核心能力,是 React 项目的必装插件。vite-plugin-compression:构建时生成 gzip 或 brotli 压缩文件,配合 Nginx 可大幅减少传输体积。vite-plugin-imagemin:压缩图片资源,减少静态资源大小。unplugin-auto-import:自动导入 React、React Router 等库的 API,无需手动写import。unplugin-icons:按需加载图标集(如 Iconify),自动 tree-shaking。rollup-plugin-visualizer:生成打包体积分析图,快速定位大模块。
插件配置示例
// vite.config.ts
import react from '@vitejs/plugin-react';
import { visualizer } from 'rollup-plugin-visualizer';
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
react(),
viteCompression({
algorithm: 'brotli', // 生成 .br 文件,压缩率更高
threshold: 10240, // 仅压缩大于 10KB 的文件
}),
visualizer({
open: true, // 构建后自动打开分析页面
gzipSize: true,
}),
],
});
自定义插件简例
如果需要在构建时替换特定字符串或打印信息,可以写一个极简插件:
function myExamplePlugin() {
return {
name: 'my-example',
transform(code, id) {
if (id.endsWith('.tsx')) {
return code.replace(/__BUILD_TIME__/g, Date.now().toString());
}
},
};
}
插件的最大价值在于“自动化”,将重复的手动工作固化为可复用的构建步骤,提升团队开发效率。
按需加载
对于大型项目,如果全量引入组件库(如 Ant Design、Arco Design)或工具库(Lodash、moment),会将大量未使用的代码打入最终包中,严重影响首屏性能。按需加载可以确保只引入实际使用到的模块和样式。
组件库按需引入
以 Ant Design 5 为例,由于它已默认支持 ES Modules 并提供了 Tree Shaking 友好的导出方式,通常无需额外配置即可实现按需引入:
// 只引入 Button,不会打包 Table、Modal 等组件
import { Button } from 'antd';
但如果你使用的是 Ant Design 4 或某些旧版组件库,需要使用 vite-plugin-imp 自动转换按需导入:
// vite.config.ts
import vitePluginImp from 'vite-plugin-imp';
export default defineConfig({
plugins: [
vitePluginImp({
libList: [
{
libName: 'antd',
style: (name) => `antd/es/${name}/style/index.css`,
},
],
}),
],
});
对于图标类需求,推荐直接使用 @ant-design/icons,同样支持 Tree Shaking。
工具库按需引入
Lodash 等工具库如果直接使用 import { debounce } from 'lodash',会将整个库引入。改用 lodash-es 并善用命名导入,即可自动 Tree Shaking:
import { debounce } from 'lodash-es';
对日期处理库(如 dayjs)而言,其本身设计就是函数式模块,天然支持按需。
打包优化
Vite 生产构建使用 Rollup,可以通过 build 配置项进行深度优化。
代码分割
合理配置 manualChunks 可以将公共依赖拆分成独立文件,避免重复打包并提升缓存命中率:
build: {
rollupOptions: {
output: {
manualChunks: {
'react-vendor': ['react', 'react-dom', 'react-router-dom'],
'antd-vendor': ['antd', '@ant-design/icons'],
'chart-vendor': ['echarts', 'echarts-for-react'],
},
},
},
}
当多个页面共享这些 vendor 包时,浏览器一次缓存后即可长期生效,后续访问其他页面无需重新下载。
压缩与混淆
生产模式下 Vite 默认使用 esbuild 进行代码压缩,速度极快。如果需要更激进的压缩效果(如去除 console、debugger),可以在 build.minify 中配置 terserOptions 或使用 esbuild 的参数:
build: {
minify: 'esbuild',
// 如果使用 terser,可配置如下
// minify: 'terser',
// terserOptions: {
// compress: {
// drop_console: true,
// drop_debugger: true,
// },
// },
}
注意:压缩和混淆会显著增加构建时间,建议仅在正式发布的生产构建中开启严格模式。
资源内联与分离
CSS 和图片等资源处理同样影响性能:
- 较小的资源(< 4KB)可以通过
build.assetsInlineLimit内联为 Base64,减少 HTTP 请求数。 - 较大的资源保持独立文件,利用浏览器并行下载和缓存机制。
build: {
assetsInlineLimit: 4096, // 小于 4KB 转 base64
}
Tree Shaking 保障
需要在 package.json 中明确设置 "sideEffects": false 或指定包含副作用的文件,告知打包工具哪些模块可以安全剔除。对于 CSS 文件,通常需要标记为副作用文件以避免被误删:
{
"sideEffects": [
"*.css",
"*.scss"
]
}
打包体积分析
强烈建议每次重大重构后用 rollup-plugin-visualizer 生成可视化报告,它会以树状图形式展示各个模块的大小占比,一眼就能定位到“为什么包这么大”。常见的大户可能是 moment.js 的本地化文件、重复打包的依赖版本等,发现后即可针对性优化。
通过插件体系的灵活扩展、组件与工具库的精确引入,以及针对性的打包配置,React 项目的生产包基本可以控制在可控的体积范围内,同时首屏加载速度也能得到质的提升。