分析打包结果

遇到这种情况首先我们先找到文件体积大的原因,借助 webpack-bundle-analyzer插件,我们可以直观看到打包后每个文件的内容和大小。

  • 第一步:安装webpack-bundle-analyzer




打包 JavaScript堆内存不足_页面加载


  • 第二步:在vue.config.js文件中引入


打包 JavaScript堆内存不足_页面加载_02


  • 第三步:在webpack配置中使用该插件


打包 JavaScript堆内存不足_pyinstaller打包减小大小_03


  • 打包时间和结果如下:


打包 JavaScript堆内存不足_pyinstaller打包减小大小_04


打包 JavaScript堆内存不足_加载_05


可以看到最大的文件达到了1.9M,打包时间146秒,页面加载时间也达到30多秒,这简直是无法忍受的。


打包 JavaScript堆内存不足_打包 JavaScript堆内存不足_06


既然我们知道了原因,就可以着手解决问题。万能的互联网上可以找到很多解决方法。例如:Gzip、cdn、splitChunk、图片压缩等等,下面会挑几个“有意思”的方法聊聊。

Gzip

gzip是GNUzip的缩写,最早用于UNIX系统的文件压缩。HTTP协议上的gzip编码是一种用来改进web应用程序性能的技术,web服务器和客户端(浏览器)必须共同支持gzip。

目前主流的浏览器,Chrome、firefox、IE等都支持该协议。常见的服务器如Apache、Nginx、IIS同样支持gzip。要使用gzip功能:

  • 第一步:在服务器端开启,以nginx为例子,在配置文件中添加下面代码


打包 JavaScript堆内存不足_pyinstaller打包减小大小_07


  • 参数解释如下:

l gzip:决定是否开启gzip模块。

l gzip_disable:(IE5.5和IE6 SP1使用msie6参数来禁止gzip压缩)。指定哪些不需要gzip压缩的浏览器(将和User-Agents进行匹配)。

l gzip_vary:增加响应头”Vary: Accept-Encoding”。

l gzip_proxied:Nginx做为反向代理的时候启用:·

off –关闭所有的代理结果数据压缩· expired –如果header中包含”

Expires”头信息,启用压缩· no-cache –如果header中包含”Cache-Control:no-cache”头信息,启用压缩·

no-store –如果header中包含”Cache-Control:no-store”头信息,启用压缩·

private –如果header中包含”Cache-Control:private”头信息,启用压缩·

no_last_modified –启用压缩,如果header中包含”Last_Modified”头信息,启用压缩·

no_etag –启用压缩,如果header中包含“ETag”头信息,启用压缩·

auth –启用压缩,如果header中包含“Authorization”头信息,启用压缩·

any –无条件压缩所有结果数据

l gzip_types:这个参数是指设置需要压缩的MIME类型,如果不在设置类型范围内的请求不进行压缩。lgzip_comp_level:设置gzip压缩等级,等级越压缩速度越快文件压缩比越小,反之速度越慢文件压缩比越大。范围是1-9,根据需求设定。

l gzip_buffers:设置用于处理请求压缩的缓冲区数量和大小。比如32 4K表示按照内存页(one memory page)大小以4K为单位(即一个系统中内存页为4K),申请32倍的内存空间。建议此项不设置,使用默认值。

l gzip_http_version:用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,所以为了支持前期版本加了此选项。默认在http/1.0的协议下不开启gzip压缩。

  • 第二步:配置完成后,需要重启一下nginx
  • 第三步:在vue项目中进行相关配置

首先安装compression-webpack-plugin插件


打包 JavaScript堆内存不足_页面加载_08


  • 第四步:在webpack配置中使用该插件


打包 JavaScript堆内存不足_页面加载_09


重新打包项目,再次访问页面我们可以看到在content-encoding一列出现了gzip,说明配置成功了,1.9M的文件压缩之后只有599k,压缩比例达到70%左右,页面加载速度有了质的飞跃,页面出现只用了3.32s。


打包 JavaScript堆内存不足_当下常用的webpack版本_10


当然,还有其他的压缩算法可以选择,例如Brotli,据说是比gzip压缩效果更好,感兴趣的读者可以试验一下。

外部引入模块(CDN)

我们可以将一些第三方组件通过cdn的方式引入,从而减小打包的文件数量,可以缩短打包时间和减小最后的文件体积。下面我们将vue、vuex、vue-router、element-ui使用cdn引入。

  • 第一步:在public/index.html文件中引入cdn链接


打包 JavaScript堆内存不足_pyinstaller打包减小大小_11


  • 第二步:在vue.config.js 配置文件中设置 externals 属性


打包 JavaScript堆内存不足_页面加载_12


其中属性名是引入的模块名,值是需要替换的变量,这个值必须和cdn中提供的一样,其作用是不打包使用外部引入的扩展,也就是build的时候不打包该模块。

  • 打包时间和结果如下:


打包 JavaScript堆内存不足_当下常用的webpack版本_13


打包 JavaScript堆内存不足_pyinstaller打包减小大小_14


可以看到打包出来的文件明显小了,chunk-vendors从1.9M减小到了1.14M。


打包 JavaScript堆内存不足_页面加载_15


打包时间为107秒,配合使用gzip页面加载时间为2.65秒,不过如果cdn链接失效会导致资源缺失。

异步组件

在开发的时候,需要合理的划分各模块,做到首屏加载的时候只读取必要的模块,其他模块在需要的时候才从服务器加载。通过这种异步加载组件的方式,在打包的时候就不会把相关的组件打包到首屏相关的js中,可以减少首屏渲染相关文件的大小。

举个例子,一开始在代码中通过下面的方式引入“floatLabel”这个组件,这个组件引入了cytoscape.js和klay.js两个库,这意味着一开始它们都会被加载(可以参考CDN模块的打包结果)。


打包 JavaScript堆内存不足_pyinstaller打包减小大小_16


但是这个floatLabel组件在最开始是不会被使用到的,于是我们通过动态引入的方式引入它。


打包 JavaScript堆内存不足_当下常用的webpack版本_17


  • 打包时间和结果如下:


打包 JavaScript堆内存不足_pyinstaller打包减小大小_18


打包 JavaScript堆内存不足_加载_19


可以看到chunk-vendors已将减少到了178.64KB,打包时间也减少到了75秒,页面出现的时间变为了1.26s。


打包 JavaScript堆内存不足_加载_20


这个时候最大的文件已经变成了klay.js、cytoscape.js和jquery.js的这个chunk,如果看着不舒服想把他们拆开,可以用splitChunks将他们拆开,或者有cdn资源的话也可以通过cdn引入。

splitChunks

splitChunks字面意思就是拆分chunks,在vue.config.js中添加下面的配置。


打包 JavaScript堆内存不足_页面加载_21


  • 打包的结果如下:


打包 JavaScript堆内存不足_加载_22


打包 JavaScript堆内存不足_页面加载_23


可以看到刚才993K的文件被拆成了几个稍微小一点的包。但是这么做对首屏加载影响不大,因为一开始都没有加载到这几个包。而且几个几百K的包和一个1M左右的包哪种方式比较好就需要进一步评估了。

总 结

上面提到的都是vue项目里面会常用到的一些webpack相关的优化,并不是说都用上了就是好的。大家需要根据项目的实际情况进行选择,没有绝对正确的优化方法,只有尝试过后才能找到最合适的打包方式。

当然还有很多别的方案没有提及,比如DllPlugin、图片压缩、Happypack等,感兴趣的朋友们可以多尝试、多比对,合适的打包方案总是要经过大量的实验得出来的。最后再推荐TerserPlugin(可以屏蔽输出)和ProgressBarPlugin(记录打包时间)两个插件,个人感觉挺好用的,其实webpack还有很多好用的插件,大家可以多多挖掘。

 

作者:黄奕鑫 编辑:詹思璇