以前作了一个React项目和Vue的项目,在作完后不加任何优化的状况下,这2个项目的首屏加载平均时间竟然达到了20+s,好一点能进10s,差一点快30s,彻底不能忍,优化势在必行,本文章记录下Vue项目的优化过程,React项目的优化后续补上。html
上图是Vue项目的首页,整个项目由vue-cli搭建,主要分为4个模块,见页面左侧导航栏,整体代码量不算太大,组件的话总共50个左右吧,项目结构见下图,不算特别大的项目,可是首屏加载时间竟然这么慢。vue
首先得肯定究竟是哪里致使了首屏渲染如此之慢?打开Chrome Network面板,勾上Disable cache选项,刷新页面观察资源加载状况,发现罪魁祸首就是webpack打包生成的app.js和vendor.js,其中vendor.js大小达到了1.2M,下载时间超过20秒,app.js也快到1M,而manifest.js不是很大。vendor.js主要是把node_modules里所用到的modules都合并成一个js了,因此比较大.而咱们也但愿将业务代码和第三方引用分开打包。manifest.js
包含webpack的runtime代码和module manifest代码,做用是防止修改了代码可是没有修改第三方库文件致使第三方库文件也打包的问题。
网上一番搜索,发现优化点主要在以下几个方面:
node
gzip是GNUzip的缩写,最先用于UNIX系统的文件压缩。HTTP协议上的gzip编码是一种用来改进web应用程序性能的技术,web服务器和客户端(浏览器)必须共同支持gzip。目前主流的浏览器,Chrome,firefox,IE等都支持该协议。常见的服务器如Apache,Nginx,IIS一样支持,gzip压缩效率很是高,一般能够达到70%的压缩率,也就是说,若是你的网页有30K,压缩以后就变成了9K左右webpack
我后端是用的express,开启gzip很是简单,首先npm install compression安装中间件,而后在app.js里添加use使用便可:
web
var compression = require('compression');
var app = express();
app.use(compression())
复制代码
重启服务,观察网络面板里面的response header,若是看到以下红圈里的字段则代表gzip开启成功vue-router
CDN(内容分发网络),是一种公共服务,他自己有不少台位于不一样地域、接入不一样运营商的服务器,而所谓的使用CDN实质上就是让CDN做为网站的门面,用户访问到的是CDN服务器,而不是直接访问到网站。因为CDN内部对TCP的优化、对静态资源的缓存、预取,加上用户访问CDN时,会被智能地分配到最近的节点,下降大量延迟,让访问速度能够获得很大提高vuex
一个原则是尽可能将比较大的第三方库放到cdn上去以减小请求时间,在个人项目中,我将vue,vuex,vue-router,echarts都放到了cdn上,具体操做是打开BootCDN 而后搜索关键字并copy连接粘贴到index.html的body闭合标签前,以下图vue-cli
externals: {
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'echarts': 'echarts'
},
复制代码
cdn使用后优点是巨大的,观察network面板,时间几乎都在50ms如下express
路由懒加载也叫延迟加载,即在须要的时候进行加载,随用随载。像vue这种单页面应用,若是没有应用懒加载,运用webpack打包后的文件将会异常的大,形成进入首页时,须要加载的内容过多,时间过长,会出现长时间的白屏,即便作了loading也是不利于用户体验,而运用懒加载则能够将页面进行划分,须要的时候加载页面,能够有效的分担首页所承担的加载压力,减小首页加载用时。
Vue官网的示例以下,采用异步组件和webpack的code-splitting结合npm
所以在项目中,进入router的index.js中,将原来的import Comp from '@/component/xxx'
改成以下,vue-router的配置项仍是保持不变
//异步组件,路由懒加载
const BookMark = resolve => require(['@/components/BookMark'],resolve);
const HotBookMark = resolve => require(['@/components/HotBookMark'],resolve);
const ImportBookMark = resolve => require(['@/components/ImportBookMark'],resolve);
const Default = resolve => require(['@/components/Default'],resolve);
复制代码
打包后查看js文件夹下的文件,会多出上述文件,每一个进行懒加载的组件都会生成一个js,以下图红框内
好比本项目里面使用的echarts,只用到了一个柱状图组件,其他的都没有用到,可是这样import后打包时却会把整个echarts都打入包内,形成空间浪费
import echarts from 'echarts'
复制代码
所以只须要import用到的组件便可,以下,这样就能够减小不少没必要要的体积
import echarts from 'echarts/lib/echars'
import 'echarts/lib/chart/bar'
import 'echarts/lib/component/legend'
import 'echarts/lib/component/title'
复制代码
小图片能够转为base64字符串而后嵌入img的src中,节省http请求数量,webpack中用url-loader处理,limit控制了图片转base64的阈值,小于该值就转base64
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
复制代码
通过上述优化后,首页打开时间迅速降低,DomContentLoaded用时不到1s,load彻底加载用时不到4s,耗时较多的是几张背景大图,原本体积就大,后续考虑放到cdn上
这是最初的优化策略,后续继续会进行深度优化。
ps:webpack-bundle-analyzer是神器,可以有效分析出包占用的体积状况~下图是最终优化后的包组成结构图,最初打包的结构图比下图大不少,主要多了echarts,vue,vue-router,vuex模块
优化后的整个包gzip后大小喜人~