前端性能,我的理解为在用户输入URL或者点击连接以后,直到网页彻底展示所须要的时间,本文暂时定义为等待时间。css
那么前端性能优化就是要缩短这个等待时间。html
等待时间没有知足用户预期。前端
缩短等待时间,达到用户预期或者技术预期。segmentfault
都知道有钱能够随心所欲,那么也能够买配置更高的电脑,速度更快的宽带,性能更好的服务器,接下来的讨论都受到贫穷的限制,没法负担得起昂贵的费用,这是一个前提(背景)。后端
由流程可知,等待时间时间主要由网络请求,页面渲染这两大方面构成。浏览器
明确目的,分解问题以后,如今是要缩短网络请求时间和页面渲染时间。缓存
由物理可知,时间=总量/速率
,想要缩短期,能够提升速率或者减小总量。性能优化
流程中,有些步骤是能够优化的,能够减小中间的某些步骤消耗的时间。服务器
老许,你要性能不要,只要你开金口,我立刻就给你想办法
不搞这些虚的了,首先从经常使用技术入手,因为经常使用技术老是变化(吐槽一下,前端技术更新比个人亚索都快),因此就找到他们的祖宗,HTML,CSS,JavaScript,其实改进他们就是具体方法,更具备可操做性。cookie
在贫穷的限制下,咱们将性能优化分解成了网络请求和页面渲染两个方面,经过优化HTML,CSS,JavaScript的方法来达到目的
HTTP遍及了互联网的每一个角落,那么对HTTP的理解,使用,优化就很重要了。
网络请求分为HTTP和非HTTP两方面,而非HTTP又分为HTML,CSS,JavaScript。
keep-alive链接,持久链接重用了TCP链接,减小了链接创建的开销,使链接保持在已谐调状态。详细参考《HTTP权威指南》 4.2.2 性能聚焦区域和4.5 持久链接
正确使用HEAD方法,能够减小传输没必要要的响应主体
使用内容编码技术,能够减少资源的体积,通常使用gzip
使用范围请求首部,能够只请求资源的一部分;甚至能够并行发送范围请求,同时获取资源的不一样部分,而后拼接回去
使用差别编码技术,能够只请求资源的变动部分,这一技术须要客户端和服务端支持
私有缓存通常由客户端提供给用户使用,共有代理缓存通常由公司提供给多个客户端使用。
缓存能够减小资源的传输,效果取决于命中率,通常有文档命中率,更精确的有字节命中率。
对比 | Expires | 👍Cache-Control |
---|---|---|
用法 | Expires: <date> | Cache-Control: max-age=<s> |
说明 | date是GMT,在date以前可使用缓存 | s是数字,单位是秒,在s秒内可使用缓存 |
注意 | 使用绝对时间,时钟不一样步会致使问题 | - |
优先级 | 低 | 高 |
标识为no-cache的响应其实是能够缓存的,只是再验证成功以后才容许使用缓存;若是再校验失败,须要缓存返回的新资源
首部 | 版本 | 备注 |
---|---|---|
Pragma: no-cache | HTTP/1.0+ | 虽然不推荐使用,可是加上能够兼容HTTP/1.0+ |
👍Cache-Control: no-cache | HTTP/1.1 |
首部 | 备注 |
---|---|
If-Modified-Since: <date> | 须要Last-Modified: <date>配合 |
If-None-Match: <tags> | 须要ETag: <tags>配合 |
对比 | Last-Modified | ETag |
---|---|---|
响应 | Last-Modified: <date> | ETag: <tags> |
请求 | If-Modified-Since: <date> | If-None-Match: <tags> |
说明 | date是GMT,验证资源在date以后有没有被修改 | tags是标识符,验证资源有没有被修改 |
程度 | 弱验证 | 可强可弱 |
注意 | 内容没有变化,可是date却变化了 内容变化了,可是不重要,date也变化了 date精确到秒,内容在亚秒级变化,date却没有变化 |
tags能够赋予多种含义,例如版本号,内容hash值等 |
强验证和弱验证的区别是:能不能惟一标识资源的一个实例
ETag,自己是强验证码,也能够做为弱验证码来用,验证会匹配字符串所有
ETag,若是加了W/前缀,就是弱验证码,验证会匹配字符串部分,只要前缀匹配,不管后面的时候同样,都会经过验证
Last-Modified,就是弱验证码,因为时间只能精确到秒,而一秒内,文件可能变化了不少次,因此是弱验证码
E-tag: "3116092995",假设这个值是文件大小,那么即便没有W/前缀,它也是弱验证码
请求/响应复用
服务端推送
首部压缩
CDN(Content Delivery Network,即内容分发网络)是一种分布式缓存,不只有缓存的优势,还有地理优点,它们一般会智能地选择与用户更近的设备提供资源。
同一个域名下的请求会不分青红皂白地携带 Cookie,而静态资源每每并不须要 Cookie 携带什么认证信息。把静态资源和主页面置于不一样的域名下,完美地避免了没必要要的 Cookie 的出现!
看起来是一个不起眼的小细节,但带来的效用倒是惊人的。以电商网站静态资源的流量之庞大,若是没把这个多余的 Cookie 拿下来,不只用户体验会大打折扣,每一年因性能浪费带来的经济开销也将是一个很是恐怖的数字。
异步能够不用等待磁盘IO,网络IO,更加有效地利用资源。
举例说明:A请求须要3s,B请求须要5s
同步须要8s,异步须要5s
同步:0s时A请求发送,3s时A请求完成,B请求发送,8s时B请求完成
异步:0s时A请求发送,B请求发送,3s时A请求完成,5s时B请求完成
同步会阻塞其余操做,异步不会阻塞其余操做,这里再也不赘述。
HTML压缩,CSS压缩,JavaScript混淆,压缩,能够减少资源的体积。
这里的压缩是指删除注释,空格,回车等没必要要的字符,和内容编码的压缩是两种方式。
CSS要尽可能精简,尽可能复用,不要定义过大的class
若是使用SCSS,过多使用mixin,function,会增长过多重复的CSS代码
举例说明,只是说明意思
<button class="bad-ok-button">OK</button> <button class="bad-cancel-button">Cancel</button> bad-ok-button { border:2px solid; border-radius:25px; background: green; }; bad-cancel-button { border:2px solid; border-radius:25px; background: red; };
<button class="good-button good-button--ok">OK</button> <button class="good-button good-button--cancel">Cancel</button> good-button { border:2px solid; border-radius:25px; }; good-button--ok { background: green; }; good-button--cancel { background: red; };
就拿Chrome来讲,有Google这个爸爸,实际上是不须要我这样的菜鸡去担心,操心浏览器渲染的优化,其实我所能作的最大的努力也是一句话,就是不添乱。
CSS资源放在head中,由于CSS下载完成才会构建CSSOM树,CSSOM树完成才会构建Render树。
JavaScript资源放在body底部,由于JavaScript会抢占控制权。
JavaScript引擎和Render引擎是相互独立的。
由于JavaScript可能会修改DOM和CSSOM,因此JavaScript执行时候,会中止渲染,由于那是徒劳的。
dns-prefetch提早进行域名解析
pre-connect提早进行TCP链接
preload,提升资源下载优先级,代表资源是如今必要的资源
prefetch,下降资源下载优先级,代表资源是以后须要的资源
不通过任何处理的状况下,下载和执行都会阻塞HTML解析
async异步下载(不阻塞),加载完成后立刻执行(阻塞),不必定会按照顺序执行
defer异步下载(不阻塞),在全部元素解析完成以后,DOMContentLoaded
事件触发以前执行(虽然阻塞,可是首次HTML解析已经完成),会按照顺序执行。
页面渲染,会通过flow和paint,而Repaint开销很大,Reflow开销更大,尽可能减小触发Reflow和Repaint,或者减小开销
display: none
,进行屡次操做后,恢复显示position
属性为absolute
或fixed
的元素,重排的开销会比较小,由于不用考虑它对其余元素的影响transform
作形变和位移CSS要尽可能简单,不要过度嵌套,不要过度使用类选择器之外的选择器
简单的CSS能够减轻渲染的压力,也更加容易修改和维护
注意:CSS选择器是从右向左进行匹配的
BEM,CSS模块化
先下载低像素的图片,既节省时间,又减少首次渲染压力;后面会下载正常像素图片,提供完美的用户体验。
图片的按需加载,不是首屏须要的图片,在须要的时候再加载
尽可能访问局部变量,尽可能减小做用域链搜索,能够加快JavaScript执行,从而更快渲染页面