(点击上方公众号,可快速关注) 作者:浪里行舟https://segmentfault.com/a/1190000016745587
引子
互联网有一项著名的8秒原则。用户在拜访Web网页时,倘若时间超过8秒就会感到不耐烦,倘若加载需要太长期,她们就会放弃拜访。大部分用户期盼网页能在2秒之内就完成加载。事实上,加载时间每多1秒,你就会流失7%的用户。8秒并不是准确的8秒钟,只是向网站研发者显示了加载时间的重要性。那咱们怎样优化页面性能,加强页面加载速度呢?这是本文重点要探讨的问题,然而性能优化是个综合性问题,无标准答案,想要面面俱到陈列出来,并非易事。本文只关注有些核心要点,以下是我总结性能优化平常的办法:
1、资源压缩与合并
重点包含这些方面:html压缩、css 压缩、js的压缩和混乱和文件合并。
资源压缩能够从文件中去掉多余的字符,例如回车、空格。你在编辑器中写代码的时候,会运用缩进和注释,这些办法无疑会让你的代码简洁况且易读,但它们亦会在文档中添加多余的字节。
1.html压缩
html代码压缩便是压缩这些在文本文件中有道理,然则在HTML中不表示的字符,包含空格,制表符,换行符等,还有有些其他道理的字符,如HTML注释亦能够被压缩。
怎样进行html压缩:
运用在线网站进行压缩(研发过程中通常不消)
nodejs 供给了html-minifier工具
后端模板引擎渲染压缩
2.css代码压缩:
css代码压缩简单来讲便是无效代码删除和css语义合并
怎样进行css压缩:
运用在线网站进行压缩(研发过程中通常不消)
运用html-minifier工具
运用clean-css对css压缩
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib1xgScnLPOGoXZfqsqGFCNhNhz9PpJxAgjv0NRqnjS93wWZiaytvGLRGnIRpwWVe3LRMiawvEP6XOyA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
3.js的压缩和混乱
js的压缩和混乱重点包含以下这几部分:
无效字符的删除
剔除注释
代码语义的缩减和优化
代码守护(代码逻辑变得混乱,降低代码的可读性,这点很重要)
怎样进行js的压缩和混乱
运用在线网站进行压缩(研发过程中通常不消)
运用html-minifier工具
运用uglifyjs2对js进行压缩
其实css压缩与js的压缩和混乱比html压缩收益要大得多,同期css代码和js代码比html代码多得多,经过css压缩和js压缩带来流量的减少,会非常显著。因此对大机构来讲,html压缩可有可无,但css压缩与js的压缩和混乱必须要有!
4.文件合并
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib1xgScnLPOGoXZfqsqGFCNhBd3vicrqY5iatzdZhibiczRMkMx4r0rwriaQkYdDTMsMGdPx0M4WcWB3MpA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
从上图能够看出不合并请求有以下缺点:
文件与文件之间有插进的上行请求,增多了N-1个网络延迟
受丢包问题影响更严重
keep-alive方式可能会显现情况,经过代理服务器时可能会被断开,亦便是说不可始终保持keep-alive的状态
压缩合并css和js能够减少网站http请求的次数,但合并文件可能会带来问题:首屏渲染和缓存失效问题。那该怎样处理这问题呢?—-公共库合并和区别页面的合并。
怎样进行文件合并
运用在线网站进行文件合并
运用nodejs实现文件合并(gulp、fis3)
2、非核心代码异步加载异步加载的方式
1、异步加载的方式
异步加载的三种方式——async和defer、动态脚本创建
① async方式
async属性是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持
async属性规定一旦脚本可用,则会异步执行
async属性仅适用于外边脚本
倘若是多个脚本,该办法不可保准脚本按次序执行
<script type="text/javascript"src="xxx.js"async="async"></script>
② defer方式
兼容所有浏览器
defer属性规定是不是对脚本执行进行延迟,直到页面加载为止
倘若是多个脚本,该办法能够保证所有设置了defer属性的脚本按次序执行
倘若脚本不会改变文档的内容,可将defer属性加入到script标签中,以便加快处理文档的速度
③动态创建script标签
在还没定义defer和async前,异步加载的方式是动态创建script,经过window.onload办法保证页面加载完毕再将script标签插进到DOM中,详细代码如下:
functionaddScriptTag(src){
varscript = document.createElement(script);
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function(){
addScriptTag("js/index.js");
}
2、异步加载的区别
1)defer是在HTML解析完之后才会执行,倘若是多个,根据加载的次序依次执行
2)async是在加载完之后立即执行,倘若是多个,执行次序和加载次序无关
async和defer
其中蓝色线表率网络读取,红色线表率执行时间,这俩都是针对脚本的;绿色线表率 HTML 解析。
3、利用浏览器缓存
针对web应用来讲,缓存是提高页面性能同期减少服务器压力的利器。
浏览器缓存类型
1.强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome掌控台的network选项中能够看到该请求返回200的状态码,并且size表示from disk cache或from memory cache;
关联的header:
Expires :response header里的过期时间,浏览器再次加载资源时,倘若在这个过期时间内,则命中强缓存。它的值为一个绝对时间的GMT格式的时间字符串, 例如Expires:Thu,21 Jan 2018 23:39:02 GMT
Cache-Control :这是一个相对时间,在配置缓存的时候,以秒为单位,用数值暗示。当值设为max-age=300时,则表率在这个请求正确返回时间(浏览器亦会记录下来)的5分钟内再次加载资源,就会命中强缓存。例如Cache-Control:max-age=300,
简单概括:其实这两者差别不大,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同期存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。因此Expires其实是过时的产物,现周期它的存在只是一种兼容性的写法。强缓存判断是不是缓存的依据来自于是不是超出某个时间或某个时间段,而不关心服务器端文件是不是已然更新,这可能会引起加载文件不是服务器端最新的内容,那咱们怎样获知服务器端内容较客户端是不是已经出现了更新呢?此时咱们需要协商缓存策略。
2.协商缓存:向服务器发送请求,服务器会按照这个请求的request header的有些参数来判断是不是命中协商缓存,倘若命中,则返回304状态码并带上新的response header通告浏览器从缓存中读取资源;另一协商缓存需要与cache-control共同运用。
关联的header:
①Last-Modified和If-Modified-Since:当第1次请求资源时,服务器将资源传递给客户端时,会将资源最后更改的时间以“Last-Modified: GMT”的形式加在实体首部上一块返回给客户端。
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
客户端会为资源标记上该信息,下次再次请求时,会把该信息附带在请求报文中一并带给服务器去做检测,若传递的时间值与服务器上该资源最后修改时间是一致的,则说明该资源无被修改过,直接返回304状态码,内容为空,这般就节省了传输数据量 。倘若两个时间不一致,则服务器会发回该资源并返回200状态码,和第1次请求时类似。这般保准不向客户端重复发出资源,亦保准当服务器有变化时,客户端能够得到最新的资源。一个304响应比一个静态资源一般小得多,这般就节省了网络带宽。
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib1xgScnLPOGoXZfqsqGFCNhomVyXrZaBHmfXQfS89lSBFBLia4JkMLmWs9185ZVMD1WaKXu1hIUcLg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
但last-modified 存在有些缺点:
Ⅰ.某些服务端不可获取精确的修改时间
Ⅱ.文件修改时间改了,但文件内容却无变
既然按照文件修改时间来决定是不是缓存尚有不足,能否能够直接按照文件内容是不是修改来决定缓存策略?—-ETag和If-None-Match
②ETag和If-None-Match:Etag是上一次加载资源时,服务器返回的response header,是对该资源的一种独一标识,只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是不是一致,就能很好地判断资源相对客户端而言是不是被修改过了。倘若服务器发掘ETag匹配不上,那样直接以常规GET 200回包形式将新的资源(当然亦包含了新的ETag)发给客户端;倘若ETag是一致的,则直接返回304知会客户端直接运用本地缓存就可。
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib1xgScnLPOGoXZfqsqGFCNhWeuBIXxH4wv4FZx25HIqKY6U6dEPDMFWWicZ7D88qRWk7QoJfUGx6rw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
两者之间对比:
首要在精确度上,Etag要优于Last-Modified。Last-Modified的时间单位是秒,倘若某个文件在1秒内改变了多次,那样她们的Last-Modified其实并无表现出来修改,然则Etag每次都会改变保证了精度;倘若是负载平衡的服务器,各个服务器生成的Last-Modified亦有可能不一致。
第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器经过算法来计算出一个hash值。
第三在优先级上,服务器校验优先思虑Etag
缓存的机制
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接运用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是不是运用缓存,若协商缓存失效,那样表率该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续运用缓存。重点过程如下:
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib1xgScnLPOGoXZfqsqGFCNh7PqQlvflXMk8Jsrn9wCuFsu2HPtJQPPtYfPZweAoNUxibGsupXyfEbg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
用户行径对浏览器缓存的影响
1.位置栏拜访,链接转是正常用户行径,将会触发浏览器缓存机制;
2.F5刷新,浏览器会设置max-age=0,跳过强缓存判断,会进行协商缓存判断;
3.ctrl+F5刷新,跳过强缓存和协商缓存,直接从服务器拉取资源。
倘若想认识更加多缓存机制,请猛戳 深入理解浏览器的缓存机制
4、运用CDN
大型Web应用对速度的追求并无止步于仅仅利用浏览器缓存,由于浏览器缓存始终只是为了提高二次拜访的速度,针对首次拜访的加速,咱们需要从网络层面进行优化,最平常的手段便是CDN(Content Delivery Network,内容分发网络)加速。经过将静态资源(例如javascript,css,照片等等)缓存到离用户很近的相同网络运营商的CDN节点上,不仅能提高用户的拜访速度,还能节省服务器的带宽消耗,降低负载。
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib1xgScnLPOGoXZfqsqGFCNhOvRy4xa1hJ29CRXibuTJUjxC0PQAHeVmg5qSjzbJr4V8ialysza1ABiaQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
CDN是怎么做到加速的呢?
其实这是CDN服务商在全国各个省份安排计算节点,CDN加速将网站的内容缓存在网络边缘,区别地区的用户就会拜访到离自己近期的相同网络线路上的CDN节点,当请求达到CDN节点后,节点会判断自己的内容缓存是不是有效,倘若有效,则立即响应缓存内容给用户,从而加快响应速度。倘若CDN节点的缓存失效,它会按照服务配置去咱们的内容源服务器获取最新的资源响应给用户,并将内容缓存下来以便响应给后续拜访的用户。因此呢,一个地区内只要有一个用户先加载资源,在CDN中创立了缓存,该地区的其他后续用户都能因此呢而受益。
5、预解析DNS
资源预加载是另一个性能优化技术,咱们能够运用该技术来预先通知浏览器某些资源可能在将来会被运用到。
经过 DNS 预解析来告诉浏览器将来咱们可能从某个特定的 URL 获取资源,当浏览器真正运用到该域中的某个资源时就能够尽快地完成 DNS 解析。例如,咱们将来可从 example.com 获取照片或音频资源,那样能够在文档顶部的 <head> 标签中加入以下内容:
<link rel="dns-prefetch" href="//example.com">
当咱们从该 URL 请求一个资源时,就再也不需要等待 DNS 的解析过程。该技术对运用第三方资源尤其有用。经过简单的一行代码就能够通知哪些兼容的浏览器进行 DNS 预解析,这寓意着当浏览器真正请求该域中的某个资源时,DNS 的解析就已然完成为了,从而节省了宝贵的时间。
另一需要重视的是,浏览器会对a标签的href自动启用DNS Prefetching,因此a标签里包括的域名不需要在head中手动设置link。然则在HTTPS下不起功效,需要meta来强制开启功能。这个限制的原由是防止窃听者按照DNS Prefetching推断表示在HTTPS页面中超链接的主机名。下面这句话功效是强制打开a标签域名解析
<meta http-equiv="x-dns-prefetch-control" content="on"/>
【关于投稿】
倘若大众有原创好文投稿,请直接给公号发送留言。
① 留言格式:【投稿】+《 文案标题》+ 文案链接② 示例:【投稿】《不要自叫作是程序员,我十数年的 IT 职场总结》:http://blog.jobbole.com/94148/③ 最后请附上您的个人简介哈~
觉得本文对你有帮忙?请分享给更加多人
关注「前端大全」,提高前端技能
![](https://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0lZCEKibSLcyLMVa3iaNzhWkSPnEBk28r5AAcL4fS03LQn1RWA5M58d7kvysRCibKpHibjs1szyRmnOQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
![](data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
|