简介
为什么要进行前端优化呢,因为这决定了用户体验,有数据表明,用户的延迟感知阈值在34ms-137ms
,平均值为65ms
(中值=54ms),也就是说如果你的网页打开速度超过这个时间,用户大几率会默默的点x
号,所以对于前端而已,性能优化特别重要,那么,大部分优化都是利用缓存,空间换时间。
HTTP Cache
基于http缓存,有以下解决方案
- expires(强缓存)
- cache-control(强缓存)
- last-modified(协商缓存)
- etag(协商缓存)
expires
设置对象的有效期,如果在设置的这个时间之前请求,那么将去读本地缓存,设置在请求头
缺点:
和本地时间做的比较,如果改了本地时间的话,那么永远读的都是缓存。
Cache-Control
以下是五种常用形式,设置在请求头
- max-age=num(s),设置最大缓存时间
- public,缓存能被多用户共享(如代理服务器)
- private,缓存不能在用户间共享,只能浏览器
- no-cache,缓存,浏览器使用缓存前,都会请求服务器缓存资源是否是最新的(协商缓存验证)。
- no-store,不能被存储
缺点:
- HTTP 1.1 才有的内容,不适用于HTTP 1.0
- 存在版本问题,到期之前的修改客户端是不可知的
Last-modified
设置对象最后修改时间,第一次请求的时候,设置last-modified
响应头,然后在第二次请求的时候,浏览器会带上这个时间,由If-Modified-Since
携带,然后服务端会进行比较,如果一致就返回304。
缺点:
- last-modified是精确到秒的,如果1s内修改文件两次,那么last-modified区分不出来
- 如果文件在一个周期内,发生了改变,但是最后又恢复到了原样,那么他最终的这个修改时间是会变的,因此协商失效。
Etag
根据内容判断,保存的可以是文件的hash
或者md5
。
在第一次请求时,设置响应头e-tag
,那么在第二次请求的时候,该e-tag
的信息会由请求头If-None-Match
携带,然后服务端会做出比较,如果相等返回304.
缺点:
- 如果文件过大,增加了服务器的计算负担。
- 分布式服务器存储的情况下,计算ETag的算法如果不一样,会导致浏览器从一台服务器上获得页面内容后到另外一台服务器上进行验证时发现ETag不匹配的情况。
这里需要注意的是,协商缓存每次都需要访问服务器,但是它返回的资源大小是不一样的。
缓存头的优先级
- 强缓存和对比缓存同时存在,如果强缓存还在生效期则强制缓存覆盖对比缓存,对比缓存不生效;如果强缓存不在有效期,对比缓存生效。即:强缓存优先级 > 对比缓存优先级
- 强缓存expires和cache-control同时存在时,则cache-control会覆盖expires,expires无论有没有过期,都无效。 即:cache-control优先级 > expires优先级。
- 对比缓存Etag和Last-Modified同时存在时,则Etag会覆盖Last-Modified,Last-Modified不会生效。即:ETag优先级 > Last-Modified优先级。
总结:Cache-Control>Expires>Etag>Last-Modified
资源缓存方案
- HTML(设置no-cache即可,利用协商)
- CSS,JS(MD5,version + 强缓存)
- image(随机名字 + 协商缓存)
需要注意,资源的缓存方案没有固定的,是需要根据自身项目需求而设定的~
本地存储
- cookie (有大小限制,单个大小约为
4KB
,而且每次都会带到服务器,占用宽带) - localStorage(有大小限制,总共大小约为
5M
,数据不安全,不应该把重要的数据存在这) - seesionStorage(不建议使用,具体要看业务场景)
- indexedDB(初始化是异步的,所以不适合前端)
请求包优化
- 代码压缩
- gzip
- 图片压缩 & 根据不同的网络情况或者不同设备使用不同的图片
减少请求
合并请求
- 合并js
- 合并css
- 使用雪碧图
避免重定向
因为一次重定向需要最少600ms
懒加载
如果首页需要加载许多图片或者是组件,都可进行懒加载。
预解析(prefetch),预加载(preload)
- preload是告诉浏览器提前加载本页的资源,从而提高该资源的优先级
- prefetch是告诉浏览器下一页需要的资源,那么浏览器会降级该资源的优先级,等到空闲的时候去下载~
CDN 加速
可以把一些静态资源,放在CDN上,优点如下所示
- 重复的利用缓存
- 更小的http request header(没有cookie)
- 提高浏览器页面并发请求数
- 缓解主域的压力
- 精确调度,优化资源加载速度
代码优化
代码优化详见我的另外一篇博客编程优化