Vue项目体积优化
上周和朋友出去吃烧烤,他挠着头说:"同样用 Vue 写后台,人家项目打包完300KB,我这直接 1.2MB,到底哪里出问题了?"
哎嘿,这种小细节就是真露脸的机会了,咱必须人前显圣一下子。
依赖相关:依赖里有脏东西!
1. 按需引入做没做?整包导入真有必要吗?
我记得很多年前第一次用 Element UI 时,我直接在 main.js 里怼了句 import ElementUI from 'element-ui',还美滋滋觉得省事。结果打包完发现光这个库就占了 200KB—— 后来才知道,没做按需引入的话,整个组件库的代码都会被拖进项目,就像你去超市只买瓶水,却扛回了整个货架。
正确操作:用 babel-plugin-component 按需抽取,比如只用到 Button 和 Select,实际打包只会包含这两个组件的代码,体积直接砍到 40KB:
// babel.config.js 配置后
import { Button, Select } from 'element-ui'; // 现在真的只引入需要的部分
Vue 3 同学直接换 Element Plus 更香,人家原生支持 ESM,Webpack 会自动摇树,连配置都省了。
2. 有好多个我在到处跑:同一个库装了三遍
有次排查发现项目同时存在 vue@2.6、vue@3.2 和 vue-template-compiler@2.6,原因是不同插件依赖不同版本。用 npm ls vue 一看,好家伙,依赖树里挂着三个 Vue 实例,相当于项目背着三个版本的代码跑。
解决办法
- 跑一遍
npm dedupe合并重复依赖,瞬间能瘦 50KB - 提交时一定要锁版本,package-lock.json 就是防止依赖乱跳的「紧箍咒」
补充点
- 除
npm ls外,推荐使用可视化工具npm list --depth=0或depcheck检测未使用的依赖,提升排查效率 - Vue 3 的
vue@3与@vue/compiler-sfc@3需版本严格对齐,否则可能导致vue-template-compiler重复引入 - 按需引入组件时,若项目同时使用 CSS 预处理器(如 SCSS),需手动引入对应样式(
import 'element-ui/lib/theme-chalk/button.css'),避免样式丢失
资源相关:图片和字体在偷吃!
1. 设计稿直接拖进项目?不再犹豫一下了?
之前接手一个后台项目,光登录页的背景图就 1.5MB,打包完发现图片占了整个包的 60%。设计师给的 PNG 没压缩,还带着透明通道,浏览器加载时相当于在下载一张高清照片。
-
开发时用 Squoosh 把 PNG 转 WebP,体积能缩 70%,肉眼几乎看不出区别
-
图标别用字体文件!我们团队之前用 iconfont 带着 200 个未使用的图标,换成 SVG sprite 后,体积从 80KB 降到 30KB,还能随意改颜色
// Vite 里加这个插件,图片打包时自动压缩
import imagemin from 'vite-plugin-imagemin';
// 配置里加上,gif、png、jpeg 全部压缩一遍
// 怕有新手在看, 提示一句要先安装了再用
npm install vite-plugin-imagemin -D
2. 来,给他们整个活,基础库咱也用上CDN
早期我总觉得把 Vue 打进包里更保险,直到发现光 Vue 3 就占了 100KB。
后来试了 CDN 方案:在 index.html 里引入
<script src="<https://unpkg.com/vue@3/dist/vue.global.prod.js>"></script>
然后在 Webpack 里配置 externals 排除,打包体积直接少了一个「Vue 大小」。
// webpack.config.js
module.exports = {
externals: {
vue: 'Vue',
'vue-router': 'VueRouter' // 若使用 Vue Router 也需排除
}
};
先别急,使用 CDN 可能存在网络延迟、CDN 服务不可用等问题,最佳实践如下
- 搭配本地 fallback(如同时提供本地副本,通过 JS 错误捕获切换)
- 选择更稳定的 CDN(如 jsDelivr、cdnjs,避免单一依赖 unpkg)
- 并非所有库都适合 CDN(如项目专属库、网络环境差的场景),建议通过
webpack-bundle-analyzer对比 - CDN 前后的体积变化和加载速度
代码相关:开发期的东西记得检查检查!
1. 生产环境还留着调试代码?console.log 在拖后腿
有次上线前忘了清日志,项目里几百个 console.log('请求成功') 全被打进包,光这部分就多了 20KB—— 相当于带着一堆没用的文件跑马拉松。更关键的是,Vue 的生产提示没关,v-if 不能和 v-for 一起用(这种毛病还能犯那是给我看哈气了) 这类警告代码也占了 30KB。
必须检查:
-
用 ESLint 禁止生产环境出现 console 和 debugger
-
Vue 2 记得在 Webpack 里加
Vue.config.productionTip = false,Vue 3 在 Vite 里设置define: { 'import.meta.env.PROD': true }
2. 所有组件一起加载?首页在背着整个项目跑
之前做一个多页面系统,首页同时加载了报表、大屏组件这些用户可能永远不会点的页面(当然这话不能让产品听到),app.js 直接冲破 800KB。后来改成路由懒加载,用户访问首页时只加载当前组件,其他页面等到点击时再加载,首屏体积瞬间腰斩。
// 不合适:首页加载所有组件
import Home from './Home.vue';
import Report from './Report.vue';
// 更好的办法:用到时再加载,打包后生成独立文件
const Home = () => import('./Home.vue');
const Report = () => import('./Report.vue');
构建相关
1. 压缩开关开了吗?别让代码裸奔
有次新人没开 Webpack 压缩,打包后的 JS 代码全是明文,体积比压缩后大了一倍。Vue CLI 虽然默认开了,但如果你加了奇怪的插件导致冲突,记得手动检查:
// Webpack 必须配置 Terser
const TerserPlugin = require('terser-webpack-plugin');
plugins: [new TerserPlugin()]
Vite 用户别以为默认压缩 CSS,加上 cssnano 能再瘦 10%。
2. 还在兼容 IE 11?现代浏览器用户不需要老补丁
如果项目面向年轻用户,那就没必要保留着大量 IE 兼容代码,
把 browserslist 改成 last 2 versions 后,polyfill 体积能直接少15%。
实战
实战案例:某中台项目体积优化对比(含第三方库与静态资源)
| 优化步骤 | 优化前 | 优化后 | 核心操作与降幅 |
|---|---|---|---|
| 初始打包 | 1.2MB | - | 未做任何优化,包含整包依赖 + 未压缩资源 |
| 1. 按需引入 Element | 1.2MB | 900KB | 移除未使用的组件代码,第三方库体积减少 25% |
| 2. 图片压缩 + CDN 分流 | 900KB | 650KB | 图片体积压缩 40%+ 排除 Vue 等基础库 100KB,合计减少 250KB |
| 3. 代码拆分 + 懒加载 | 650KB | 400KB | 首屏仅加载必要组件,非首屏代码延迟加载,减少 35% |
| 4. 构建层优化(压缩 + 去兼容) | 400KB | 280KB | 开启压缩 + 移除 IE 兼容代码,最终体积再降 30% |
实际的体验就是打包时间快了一倍,本地启动、首页加载速度比之前快了不止一点半点,切换页面时几乎没有等待感。
最关键的是用 webpack-bundle-analyzer 生成可视化报告,能清楚看到哪个文件在「增重」,就像给项目做 CT 扫描,哪里有问题一目了然。