Vue2 首屏加载慢打包优化的详细记录
在前端项目开发过程中,首屏加载速度直接影响用户体验,尤其是对于 Vue2 项目而言,随着业务功能的不断迭代,依赖包增多、代码量增大,很容易出现首屏加载缓慢的问题。近期我负责的一个 Vue2 项目就遇到了这样的情况,用户反馈打开首页时需要等待较长时间,甚至偶尔会出现页面卡顿的现象。为了解决这个问题,我进行了一系列的排查与优化,现将整个过程详细记录下来,希望能为遇到类似问题的同学们提供一些参考。
一、问题排查:定位首屏加载慢的根源 🔍
当发现项目首屏加载慢后,我首先想到的是通过浏览器的开发者工具(F12)来查看页面加载资源的情况。打开 F12 进入 “Network” 面板,刷新首页后,结果让我很惊讶:多个文件的加载时间竟然长达十几秒,这无疑是导致首屏加载慢的主要原因。

经过仔细筛选和分析,我发现主要有 4 个文件的加载情况异常,具体如下:
- jsmap.js:文件大小达到了 3807k,如此大的文件体积在加载过程中必然会消耗大量的时间和带宽,严重影响首屏加载速度。
- vendor.js:文件大小为 2405k,作为项目依赖包的打包文件,其体积过大也会对首屏加载造成不小的压力。
- app.js:文件大小为 577k,虽然相比前两个文件体积小一些,但作为项目的核心业务代码文件,其加载效率也直接关系到首屏的渲染速度。
- modules.js:该文件本身大小并不大,但通过观察加载顺序发现,它需要等待前面几个大文件加载完成后才开始加载,这种加载顺序的依赖关系会导致页面在这一阶段出现卡顿,用户只能等待所有文件加载完成后才能正常操作页面。
明确了这 4 个主要卡顿的文件后,接下来我便针对每个文件展开深入排查,分析它们在项目中的使用场景和加载方式,以便制定针对性的优化方案。
二、分文件优化:逐个突破加载难题 💡
(一)jsmap.js 与 modules.js:优化加载范围,避免全局引入 📦
首先对 jsmap.js 和 modules.js 进行排查,通过查看项目的路由配置、组件引入代码以及相关的业务逻辑文件,我发现这两个文件并非在项目的所有页面中都有使用,而仅仅是在特定的几个页面(如数据统计页面、复杂表单页面)中才会用到。
但在当前的项目配置中,这两个文件却是在index.html中进行全局引入的,这就意味着即使是不需要使用这两个文件的页面,在加载时也会被迫加载它们,不仅增加了不必要的加载时间和带宽消耗,还影响了首屏的加载速度。
针对这一问题,我的优化方案是将这两个文件的引入方式从全局引入改为在特定页面中按需引入。具体操作步骤如下:
- 首先在index.html中删除对 jsmap.js 和 modules.js 的引入代码,取消全局加载配置。
- 然后在需要使用这两个文件的特定页面组件中,通过import语句在组件的脚本部分进行局部引入,例如在数据统计页面的组件中:
// 数据统计页面组件
import 'path/to/jsmap.js'; // 仅在该页面引入
import 'path/to/modules.js'; // 仅在该页面引入
export default {// 组件相关代码
}通过这样的修改,只有当用户访问到这些特定页面时,才会加载对应的文件,避免了在首屏加载时就加载不必要的资源,有效减轻了首屏的加载压力。
(二)app.js:开启路由懒加载,减少初始加载体积 🛣️
对于 app.js 文件,其主要包含了项目的核心业务代码和路由相关配置。为了找出其加载慢的原因,我查阅了 Vue2 项目优化的相关资料,发现路由没有使用懒加载是导致 app.js 体积过大、加载慢的常见原因之一。
带着这个疑问,我查看了项目的路由配置文件(router/index.js),果然发现项目中所有的路由组件都是通过直接import的方式进行引入的,并没有使用懒加载。这种方式会导致在项目打包时,所有路由组件的代码都会被打包到 app.js 中,使得 app.js 的体积增大,进而影响首屏加载速度。
针对这一问题,我将路由引入方式修改为懒加载模式。Vue2 中实现路由懒加载主要有两种方式:使用Vue异步组件和ES6的import()语法。考虑到代码的简洁性和兼容性,我选择使用 ES6 的import()语法来实现,具体修改如下:
修改前(非懒加载):
// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
// 直接引入所有路由组件,打包时会全部加入app.js
import Home from '@/components/Home';
import About from '@/components/About';
import User from '@/components/User';Vue.use(Router);export default new Router({routes: [{path: '/',name: 'Home',component: Home},{path: '/about',name: 'About',component: About},{path: '/user',name: 'User',component: User}]
});修改后(懒加载):
// router/index.js
import Vue from 'vue';
import Router from 'vue-router';Vue.use(Router);export default new Router({routes: [{path: '/',name: 'Home',// 懒加载:只有访问该路由时才加载组件component: () => import('@/components/Home') },{path: '/about',name: 'About',component: () => import('@/components/About')},{path: '/user',name: 'User',component: () => import('@/components/User')}]
});通过开启路由懒加载,项目在首屏加载时只会加载当前路由对应的组件代码,而不是将所有路由组件的代码都打包到 app.js 中一次性加载,这样大大减小了 app.js 的初始加载体积,显著提升了首屏加载速度。
(三)vendor.js:拆分大依赖包 + 清理废弃依赖,缩减文件体积 🗑️
vendor.js 是 Vue2 项目中用于打包第三方依赖包(如 vue、vue-router、axios、element-ui 等)的文件,其体积大小与项目中安装的依赖包密切相关。为了找出 vendor.js 体积过大的具体原因,我首先执行了npm run build --report命令,该命令会在打包完成后生成一个依赖包分析报告页面,通过这个页面可以清晰地看到各个依赖包在 vendor.js 中所占的体积比例。

打开生成的分析报告后,我发现有几个依赖包所占的体积比例较大,分别是:
- echarts(图表库)
- element-ui(UI 组件库)
- lodash(工具函数库)
这三个依赖包的总大小占据了 vendor.js 的很大一部分,是导致 vendor.js 体积过大的主要原因。
此外,我还对项目的package.json文件进行了排查,发现其中存在几个已经废弃不用的依赖包(如早期项目中使用的某个旧版本表单验证库、一个不再维护的日期处理库),这些废弃依赖包虽然不再被项目使用,但在打包时仍然会被打包到 vendor.js 中,进一步增加了文件体积。
针对 vendor.js 的优化,我制定了以下两个方案并逐步实施:
1. 配置 webpack,拆分大依赖包 🧩
Vue2 项目默认使用 webpack 进行打包,因此我通过修改webpack.prod.conf.js配置文件,将echarts、element-ui和lodash这三个大的依赖包从 vendor.js 中拆分出去,单独打包成独立的文件,实现按需加载。
具体修改步骤如下:
- 打开项目根目录下的build/webpack.prod.conf.js文件。
- 在module.exports的optimization(若没有则新增)配置项中,添加splitChunks配置,用于拆分依赖包:
// webpack.prod.conf.js
module.exports = {// 其他配置项...optimization: {splitChunks: {chunks: 'all', // 对所有类型的chunk进行拆分cacheGroups: {// 拆分element-ui:单独打包成chunk-element-ui.jselementUi: {name: 'chunk-element-ui',test: /[\\/]node_modules[\\/]element-ui[\\/]/,priority: 20 // 优先级,数值越大越先被拆分},// 拆分echarts:单独打包成chunk-echarts.jsecharts: {name: 'chunk-echarts',test: /[\\/]node_modules[\\/]echarts[\\/]/,priority: 20},// 拆分lodash:单独打包成chunk-lodash.jslodash: {name: 'chunk-lodash',test: /[\\/]node_modules[\\/]lodash[\\/]/,priority: 20},// 其他第三方依赖包打包到chunk-vendor.js(原vendor.js)vendor: {name: 'chunk-vendor',test: /[\\/]node_modules[\\/]/,priority: 10, // 优先级低于上面的大依赖包chunks: 'initial'}}}}// 其他配置项...
};通过上述配置,webpack 在打包时会将element-ui、echarts和lodash分别打包成独立文件,而不是全部打包到 vendor.js 中。同时,这些拆分后的文件会根据页面的使用情况进行按需加载,只有当页面中使用到对应的依赖包时,才会加载相关的文件,有效减小了 vendor.js 的体积。
2. 清理废弃依赖,减少不必要的打包 🚮
在完成大依赖包的拆分后,我又对package.json中的依赖包进行了全面清理。具体步骤如下:
- 列出所有不再被项目使用的废弃依赖包名称(可通过全局搜索依赖包名确认是否被引用)。
- 通过npm uninstall 依赖包名称命令将它们逐个从项目中卸载,例如卸载某个废弃的表单验证库:
npm uninstall old-form-validator- 卸载完成后,重新执行npm install命令安装项目所需的依赖包,确保项目依赖环境的干净和整洁。
通过清理废弃依赖,进一步减少了不必要的代码打包,使得 vendor.js 的体积得到了额外的缩减。
三、优化效果:首屏加载速度较大提升 📈
在完成上述所有优化措施后,我重新对项目进行了打包,并通过浏览器开发者工具再次测试首屏加载速度。测试结果显示,优化后的首屏加载情况得到了显著改善:
- 原本需要十几秒加载的 4 个主要文件,加载时间均大幅缩短,其中 jsmap.js 和 modules.js 由于改为按需引入,在首屏加载时不再被加载,直接减少了首屏的加载资源;
- app.js 的体积从原来的 577k 减小到了约 300k,加载时间从原来的 5 秒左右缩短到了 1.5 秒以内;
- vendor.js 的体积从原来的 2405k 减小到了约 800k,加载时间从原来的 8 秒左右缩短到了 2 秒以内;
- 整个首屏的加载时间从原来的十几秒缩短到了 3-4 秒,页面卡顿现象完全消失,用户体验得到了极大的提升。
同时,通过npm run build --report生成的新依赖分析报告可以看到,各个依赖包的打包情况更加合理,没有出现过大的单个文件,依赖包的拆分和清理工作达到了预期的效果。

四、总结与思考 📝
本次 Vue2 首屏加载慢的打包优化工作,通过定位问题、分文件制定优化方案并逐步实施,最终取得了较大的优化效果。在整个优化过程中,我总结出以下几点经验和思考:
善用工具排查问题:在遇到首屏加载慢等性能问题时,首先要通过浏览器开发者工具、webpack 依赖分析报告等工具,精准定位导致问题的根源,避免盲目优化。
按需引入是关键:对于项目中的资源文件(如 JS 文件、CSS 文件)和依赖包,应尽量采用按需引入的方式,避免全局引入导致的资源浪费和加载速度变慢。
合理配置 webpack:webpack 作为 Vue2 项目的主要打包工具,其丰富的配置选项可以帮助我们实现依赖包拆分、代码压缩、按需加载等多种优化功能,熟练掌握 webpack 的相关配置对于项目优化至关重要。
定期清理项目依赖:随着项目的迭代,很容易出现废弃依赖包堆积的情况,定期对项目依赖进行清理,不仅可以减小打包文件的体积,还能避免废弃依赖包带来的潜在风险(如安全漏洞、兼容性问题等)。
当然,Vue2 项目的首屏加载优化还有很多其他的方法,例如开启 Gzip 压缩、使用 CDN 加载第三方依赖、优化图片等静态资源、减少首屏不必要的 DOM 渲染等。在后续的项目开发中,我会继续探索更多有效的优化手段,不断提升项目的性能和用户体验。
如果大家在 Vue2 项目优化过程中还有其他更好的方法或经验,欢迎在评论区留言交流,共同学习和进步!🎉
