WebPack实例与前端性能优化
【前端构建】WebPack实例与前端性能优化
计划把微信的文章也搬一份上来。
这篇主要介绍一下我在玩Webpack过程中的心得。通过实例介绍WebPack的安装,插件使用及加载策略。感受构建工具给前端优化工作带来的便利。
壹 | Fisrt

曾几何时,我们是如上图的方式引入JS资源的,相信现在很少遇见了。近年来Web前端开发领域朝着规范开发的方向演进。体现在以下两点:
MVC研发构架。多多益处(逻辑清晰,程序注重数据与表现分离,可读性强,利于规避和排查问题...)
构建工具层出不穷。多多益处(提升团队协作,以及工程运维,避免人工处理琐碎而重复的工作)
- 模块化开发
- 将前端性能优化理论落地,代码压缩,合并,缓存控制,提取公共代码等
- 其他的还包括比如你可以用ES 6 或CoffeeScript写源码,然后构建出浏览器支持的ES5
所以,前端这么好玩,如果还有项目没有前后端分离的话,真的是守旧过头了。
主流构建工具
市面上有许多构建工具,包括Grunt、Gulp、browserify等,这些和WebPack都是打包工具。但WebPack同时也具备以下特点:
相比Grunt,WebPack除了具备丰富的插件外,同时带有一套加载(Loader)系统。使它支持多种规范的加载方式,包括ES6、CommonJS、AMD等方式,这是Grunt、Gulp所不具备的。
从代码混淆的角度来看,WebPack更加的极致
代码分片为处理单元(而不是文件),使得文件的分片更为灵活。
P.S.此处只做简单的比较,不论孰优孰劣。其实工具都能满足需求,关键是看怎么用,工具的使用背后是对前端性能优化的理解程度。
貳 | Second
WebPack安装与使用
WebPack运行在 NodeJS之下,并且它及其插件都是使用NPM(NodeJS的包管理工具)管理。
安装Node及NPM。到NodeJS官网安装包,安装即可
全局安装WebPack。联网情况下,执行命令行 $npm install webpack -g 即可。
此至即可使用WebPack了,到WebPack官网去按着Get start(http://webpack.github.io/docs/tutorials/getting-started/)的步骤来,感受一个最简单的构建过程。
然而要把WebPack用好,只是跑起来是远远不够的。
叁 | Third
WebPack插件
花较大篇幅介绍插件的使用,以下通过在一个DemoApp的构建过程中思考的一些问题(这些问题基本会在每个项目中遇到),让这些插件逐一登场。
一、文件过大
DemoApp最初的构建结果如下:

这里生成了一个topic.xxx.js,这个文件本来很小,估计只有10Kb左右,但构建的结果居然快1Mb了。在3G网络(750Kb/s)下的加载瀑布流如下图:

这张图(体现前端文件加载过程)曝露了几个问题:
上面箭头所指的很蓝色柱子,说明了大部分时间消耗在加载topic.xxxx.js上。
所有JS文件相关的柱子是一根结束了另一根才开始,说明不合理的文件合并策略,导致文件串行加载。
结果就是如底部的箭头所看到的,页面的加载时间太长了(3G网络,10+秒)。
观察构建的文件,发现原来构建工具把React、jQuery等代码库合并到了topic.xxxx.js,造成此文件过大。如果再加一个activity模块呢?很明显,activity.xxx.js得到类似的结果,都太大了,并且React、jQuery等代码库重复被合并到activity和topic里,如下图。如果再加模块也会得到同样的结果,模块越多重复加载的情况越严重。

可见,提取公共代码,情况可以得到改善,另外,压缩代码无疑是可以使文件变小的。
1. 提取React、jQuery等库文件。它们很少变化,并且到处被复用,应该被提取出来,并且得到长时间的缓存。
此处使用插件:WebPack.optimize.CommonsChunkPlugin(WebPack内建插件)

2. 代码压缩。React由700+ Kb压缩成100+ Kb
此处使用插件:WebPack.optimize.UglifyJsPlugin (WebPack内建插件)

处理后topic.xxx.js和activity.xxx.js都很小了,并且多了jquery.xxx.js和react.xxx.js

再看看文件加载的瀑布流,柱子所占比例短了,同时资源并行加载。

到此为止,这个问题算比较好地解决了,但还不够,随着项目越来越大,还有一个重要因素会导致文件很大。这部分内容放到本文的最后介绍。
二、如何缓存
缓存控制要做到两件事情,提到缓存命中率
对于没有修改的文件,从缓存中获取文件
对于已经修改的文件,不要从缓存中获取
围绕这两点,演绎出了很多方案,此处列两种:
不处理,等待用户浏览器缓存过期,自动更新。这是最偷懒的,命中率低一些,同时可能会出现部分文件没有更新,导致报错的情况。
Http头对文件设置很大的max-age,例如1年。同时,给每个文件命名上带上该文件的版本号,例如把文件的hash值做为版本号,topic. ef8bed6c.js。即是让文件很长时间不过期。
当文件没有更新时,使用缓存的文件自然不会出错;
当文件已经有更新时,其hash值必然改变,此时文件名变了,自然不存在此文件的缓存,于是浏览器会去加载最新的文件。
从上面的截图可以看出来,通过WebPack是可以很轻松做到第二点的——只需要给文件名配置上[chunkhash:8]即可,其中8是指hash长度为8,默认是16。

P.S.这样的处理效果已经很好了,但同样有劣处,即浏览器给这种缓存方式的缓存容量太少了,只有12Mb,且不分Host。所以更极致的做法是以文件名为Key,文件内容为value,缓存在localStorage里,命中则从缓存中取,不命中则去服务器取,虽然缓存容量也只有5Mb,但是每个Host是独享这5Mb的。
三、自动生成页面
文件名带上版本号后,每一次文件变化,都需要Html文件里手动修改引用的文件名,这种重复工作很琐碎且容易出错。

使用 HtmlWebpackPlugin 和 ExtractTextPlugin 插件可以解决此问题。
生成带JS的页面

- 生成带css的页面
new ExtractTextPlugin("comm.[contenthash:9].css")
插件介绍到此为止,然而,还有一个关于同步加载和异步加载的问题,否则入口文件还是会很臃肿。
肆 | Fourth
关于同步加载和异步加载
使用WebPack打包,最爽的事情莫过于可以像服务器编程那样直接require文件,看起来是同步地从服务器上取得文件直接就使用了。如下面的代码一样,没有任何异步逻辑,代码很干净。

然而,这种爽是有代价的,对于直接require模块,WebPack的做法是把依赖的文件都打包在一起,造成文件很臃肿。
所以在写代码的时候要注意适度同步加载,同步的代码会被合成并且打包在一起;异步加载的代码会被分片成一个个chunk,在需要该模块时再加载,即按需加载,这个度是要开发者自己把握的,同步加载过多代码会造成文件过大影响加载速度,异步过多则文件太碎,造成过多的Http请求,同样影响加载速度。
同步加载的写法,如:
var TopicItem = require('../topic/topicitem');
异步加载的写法,如:

一个原则是:首屏需要的同步加载,首屏过后才需要的则按需加载(异步)
结语
以上是WebPack构建工具比较好的实践,可见,要用好还是很考验前端性能优化的功力的,比较什么时候同步,什么时候异步,如果做缓存等等。
WebPack实例与前端性能优化的更多相关文章
- 【前端构建】WebPack实例与前端性能优化
计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给前端优化工作带来的便利. 壹 | Fisrt 曾几 ...
- vue-小爱ADMIN系列文章(二):微信微博等分享,国际化,前端性能优化,nginx服务器部署
最近在做我的小爱ADMIN后台管理系统,结合当前市场后台管理系统对相关功能的需求,我又开始新增了一些新的功能和组件,如分享功能组件,项目国际化功能:项目完成后,部署在nginx服务器,发现首次访问的速 ...
- 【前端性能优化】高性能JavaScript整理总结
高性能JavaScript整理总结 关于前端性能优化:首先想到的是雅虎军规34条然后最近看了<高性能JavaScript>大概的把书中提到大部分知识梳理了下并加上部分个人理解这本书有参考雅 ...
- 前端性能优化--图片处理(Css Sprites 与 base64)
前言: 近期研究着前端性能的优化方面的知识,并以博客记之.之前有相同系列的文章(前端性能优化--图片懒加载(lazyload image)),这次继续是关于图片的处理,css sprites 和 ba ...
- 前端性能优化之gzip
前言: 如果你是个前端开发人员,你肯定知道线上环境要把js,css,图片等压缩,尽量减少文件的大小,提升响应速度,特别是对移动端,这个非常重要.常用的前端性能优化方法有如下几种 一.减少http请求 ...
- 前端性能优化成神之路—资源合并与压缩减少HTTP请求
资源合并与压缩减少HTTP请求的概要 资源合并与压缩减少HTTP请求主要的两个优化点是减少HTTP请求的数量和减少请求资源的大小 http协议是无状态的应用层协议,意味着每次http请求都需要建立通信 ...
- 前端性能优化JavaScript篇
关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好.前面我写了一篇关于css优化的总结文章,今天再从javascript方面聊一聊. 1.从资源加载方面来说,浏览器的 ...
- Js基础知识(五) - 前端性能优化总结
前端性能优化总结 资源优化 缓存 最好的资源优化就是不加载资源.缓存也是最见效的优化手段.说实话,虽然说客户端缓存发生在浏览器端,但缓存主要还是服务端来控制,与我们前端关系并不是很大.但还是有必要了解 ...
- Web前端性能优化总结——如何提高网页加载速度
一.提高网页加载速度的必要性 国际知名的一组来自Jupiter Research的数据显示:购物者在访问网站过程中的不满会导致销售损失和品牌受损,其中 77%的人将不再访问网站 ,62%的人不再从该网 ...
随机推荐
- 枚举类型互相转换(使用GetEnumName和TypeInfo两个函数)
usesClasses,TypInfo ; typeTCommandType = (ctEmptyCommand,ctAdd,ctModify); TCommandTypeConvert=classp ...
- 新的方法 (New Approach)¶
第一章:简介 - ANSI Common Lisp 中文版 新的方法 (New Approach)¶ 本书的目标之一是不仅是教授 Lisp 语言,而是教授一种新的编程方法,这种方法因为有了 Lisp ...
- Java 建立mysql数据库连接的语句
每次在面试时被问到jdbc的数据路链接过程都卡着,这次不怕了,背会了... 第一个,比较粗糙的 try{ Class.forName("com.mysql.jdbc.Driver&quo ...
- 关于Oralce数据库优化的几点总结
个人理解,数据库性能最关键的因素在于IO,因为操作内存是快速的,但是读写磁盘是速度很慢的,优化数据库最关键的问题在于减少磁盘的IO,就个人理解应该分为物理的和逻辑的优化, 物理的是指oracle产品本 ...
- Delphi过程函数传递参数的八种方式
今天一同事问我为什么有些过程函数里面有Var而有些没有,不解,遂到网上百度,得解.快哉,快哉. 在Delphi过程.函数中传递参数几个修饰符为Const.Var.Out.另一种不加修饰符的为默认按值传 ...
- GNU C的使用
基本语法 gcc [options] [filenames] 说明: 在gcc后面可以有多个编译选项,同时进行多个编译操作.很多 的gcc选项包括一个以上的字符.因此你必须为每个选项指定各 自 ...
- hdu3829(最大独立集)
传送门:Cat VS Dog 题意:动物园有N只猫,M只狗,P个小孩.每个小孩都有自己喜欢的动物和讨厌的动物,如果他喜欢狗,那么就讨厌猫, 如果他讨厌狗,那么他就喜欢猫.某个小孩能开心,当且仅当他喜欢 ...
- DHTML【10】--Javascript
大家好,这一节主要介绍Javascript的函数.函数是Javascript的核心中的核心,这么强调一点都不过分,相信没有人反对,如果有人反对,你以后可以不用函数,呵呵,说的有点绝了啊. 下面看一下J ...
- uva 1434 - YAPTCHA(数论)
题目链接:uva 1434 - YAPTCHA 题目大意:给定n和k,求题目中给定的式子S(n). 解题思路:威尔逊定理,x为素数时有,((x−1)!+1)%x==0,所以对于本题.假设3*k+7为素 ...
- Help Johnny-(类似杭电acm3568题)
Help Johnny(类似杭电3568题) Description Poor Johnny is so busy this term. His tutor threw lots of hard pr ...