web性能优化之--合理使用http缓存和localStorage作资源缓存

1、前言css

       开始先扯点别的:html

  估计不少前端er的同窗应该遇到过:在旧项目中添加新的功能模块、或者修改一些静态文件时候,当代码部署到线上以后,需求方验收OK,此时你送了一口气,当你准备开始得意于本身的masterpiece时候,忽然需求方跑来和你说,不少用户反应仍是没有看到新的效果,或者某个图片仍是旧的。。。。what? 估计你第一反应就是,确定是可恶的缓存搞的鬼。我遇到这样几种状况;前端

      一、在某个旧项目中,咱们的静态资源部署主要是在每次更新的时候自动添加版本号的形式,好比在后面加上版本?v=时间戳,按理来讲,发布代码以后,用户应该拉取的是最新的资源,可是事与愿违,就是有的浏览器直接忽略后面的版本号,获取旧的资源;处理办法通常是:再在静态资源后面继续加一个版本号再发布一次。这样就OK了。虽然是OK了,但这就引起了一个前端代码部署问题,看这里:《大公司里怎样开发和部署前端代码》git

      二、在某个Hybrid开发中,客户端吊起一个webview,若是这个资源是用户常常访问的且这个文件常常变更(例如直播中的某次抢红包等特效)的,须要后台在配置这连接必须每次加上一个最新的版本号,否则大几率会有用户访问旧的页面。可是这个还不必定够,以前就遇到过,修改看版本仍是不行,明明就是缓存问题,可是你却无能为力,你总不能要求用户去清缓存吧?后面硬让运维清了cdn才有效果,坑得不行。github

      三、某个新项目中采用非覆盖式的文件模式,即便每次有变更以后,静态资源就会更换不一样的hash名,这样就能够避免用户访问到旧的资源了。这也是如今比较流行的方案。web

     上面讲的都是本地缓存带来的困扰,可是正是由于浏览器这种缓存策略,提升了web的性能,也节约了不少开销。算法

     用户主动触发的页面刷新行为(好比刷新按钮、右键刷新、F5等),会致使浏览器放弃本地缓存,使用协商缓存(304缓存)。后端

     下面讲讲http缓存策略。浏览器

2、浏览器缓存缓存

  浏览器缓存分为强缓存和协商缓存。后面会介绍。
  1.浏览器请求某资源,经过header判断是否强缓存,如果强缓存,则从本地直接获取缓存文件,不发请求到浏览器
  2.若不是强缓存,发送请求到服务器,服务器经过一些request header肯定是不是协商缓存,若是是,服务器将请求返回,状态码304,但不返回资源,而是让客户端从本地缓存获取资源
  3.强缓存和协商缓存,资源都是本地,只是强缓存不会发送请求到服务器,协商缓存会发送请求到服务器。

3、http缓存策略

一、常见http报头

Accept: text/html,image/*                                      #浏览器能够接收的类型
Accept-Encoding: gzip,compress                                 #浏览器能够接收压缩编码类型
Accept-Language: en-us,zh-cn                                   #浏览器能够接收的语言和国家类型
Host: www.lks.cn:80                                            #浏览器请求的主机和端口
If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT               #某个页面缓存时间
Referer: http://www.qq.com/                                    #请求来自于哪一个页面
User-Agent: Mozilla/4.0 compatible; MSIE 5.5; Windows NT 5.0   #浏览器相关信息
Cookie:                                                        #浏览器暂存服务器发送的信息
Connection: close1.0/Keep-Alive1.1                             #HTTP请求的版本的特色
Date: Tue, 11 Jul 2000 18:23:51GMT                             #请求网站的时间
Allow:GET                                                      #请求的方法 GET 常见的还有POST
Keep-Alive:5                                                   #链接的时间;5
Connection:keep-alive                                          #是不是长链接
Cache-Control:max-age=600                                      #缓存的最长时间 600s

二、设置强缓存

  Cache-Control: 缓存控制策略,值可能有public/private max-age=xxxx/no-store/no-cache。public/private定义文件是否容许中继缓存(好比CDN)对其缓存,private仅容许浏览器缓存文件而不容许中继缓存存储文件,public都容许。max-age=xxxx/no-store/no-cache定义文件的缓存时长,max-age定义文件在指定的时间内无需去服务端检查是否有更新,单位是秒;no-store简单粗暴,禁止任何中继缓存和浏览器存储任何响应;no-cache指定浏览器每次都要去服务端检查文件是否有更新。

  Expires: 文件的绝对过时时间,在过时前,再次请求同一文件不会和服务端交互,而是直接从缓存里取。Expires属性的行为受Cache-Control属性影响,当响应头里同时又Cache-Control属性,且Cache-Control属性的值有max-age时,max-age优先级大于Expires,会重写Expires的值。Expires由于使用绝对时间,因此它的缺点是须要客户端和服务端保持时间同步,它的优势是在文件过时前和服务端彻底没有交互,对于追求性能极致的网站有很大的诱惑力。且Expires属性是http1.0定义的,对于不支持http1.1的浏览器来讲很宝贵。Cache-Control 的选择更多,设置更细致,若是同时存在的话,优先级高于 Expires。

  通常的:

  HTTP 信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0 等告诉浏览器不用缓存的请求

  须要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的

  通过HTTPS安全加密的请求(有人也通过测试发现,ie 其实在头部加入 Cache-Control:max-age 信息,firefox 在头部加入 Cache-Control:Public 以后,可以对HTTPS的资源进行缓存)

  HTTP 响应头中不包含 Last-Modified/Etag,也不包含 Cache-Control/Expires 的请求没法被缓存

三、设置协商缓存

  3.一、 request中的:

     If-Modify-Since: 请求头中带的浏览器缓存里保存的上次响应时保存的文件最后修改时间

     If-None-Match: 请求头中带的浏览器缓存里保存的上次响应时保存的文件ETag

  3.二、response中的:

     Last-Modified: 资源的最后修改时间,注意是文件的修改时间不是建立时间

     Etag: 即Entity Tag,标识一个文件特定版本的字符串,多是基于文件内容的哈希值或者是其它指纹码,不一样服务器实现方式不一样 

  3.三、检查更新的途径有多种,第一种是根据文件修改时间,request带If-Modify-Since即上次response中的Last-Modified,去服务端校验文件是否更新;二是根据文件的ETag,request带If-None-Match即上次response中的Etag,去服务端校验文件是否更新。我知道你必定会问request中f-Modify-Since和If-None-Match都有的话,是知足一个服务端就返回304吗?答案是否认的,须要二者都知足才会返回304。主要是基于如下几个缘由:
  a、Last-Modified 标注的最后修改时间只能精确到秒,服务器都是精确到毫秒级别的。若是有些资源在一秒以内被屡次修改的话,他就不能准确标注文件的新鲜度了;
  b、若是某些资源会被按期生成,当内容没有变化,但 Last-Modified 却改变了,致使文件没使用缓存;
  c、有可能存在服务器没有准确获取资源修改时间,或者与代理服务器时间不一致的情形。

四、 get请求和post请求

  4.1get:

    请求可被缓存;

    请求保留在浏览器历史记录中

    请求可被收藏为书签

       请求不该在处理敏感数据时使用

    请求有长度限制

       请求只应当用于取回数据

     4.2post:

     请求不会被缓存

     请求不会保留在浏览器历史记录中

     不能被收藏为书签

     请求对数据长度没有要求

  因此要想在客户端作HTTP的缓存必定要注意使用GET请求!

五、维护

  5.一、若是后端是有专人写的话,缓存设置就须要他们配合,事实上,如今有专门的运维童鞋去维护这些,包括一些cdn的设置;

  5.二、http缓存毕竟是web性能优化之一,也是前端er须要了解掌握的基础知识之一。

 

3、localStorage资源缓存

以前为了长时间缓存一些资源或者状态有使用过localStorage,前段时间看微信公众号的文章时候,微信把生成页面的js都缓存到localStorage中,这算是一个比较新的缓存控制“黑科技”。

 

追根溯源,找到手机腾讯网前端团队带有增量更新特点的 js模块管理框架-MT,MT有如下好处;

一、在快速迭代版本过程当中,咱们有时候只修改了某个js中的几行代码,却须要用户下载整个js文件,这在重视流量的移动端显得很是浪费,mt首创的加强更新算法实现了修改多少代码就只下载修改代码的功能,为用户和公司节省大量流量

二、localstorage里面存储的上个版本的js内容和版本号,当本次版本号和上次版本号不一致的时候,mt拼接出增量文件url去拉取增量文件,并和上个版本的js内容合并生成新版本内容。整个方案得核心在于增量文件得计算和合并

 

localStrorage虽有有永久缓存大量数据的功能,可是要实现这个方案,还需考虑几个问题:

一、版本更新机制

二、搭建更新代码的脚手架--微信本身开发的moon.js

二、存在xss安全隐患,毕竟客户端的代码能够任意修改。

 

4、静态资源储存在localStorage上有什么优缺点?

一、兼容性不太好,不支持LS的浏览器比例仍然很大;

二、静态资源采用LS缓存存在安全隐患;

三、非首屏的css能够用LS缓存,首屏若是要考虑SEO,不能使用LS;

四、执行速度,读取后使用eval或建立<script>标签的时间会比浏览器直接加载慢。

五、版本控制,须要本身写一套版本控制机制。

六、localStorage以页面的域名划分,而常见的静态资源都以资源自己的域名来缓存,意味着若是你的应用有多个等价域名,它们之间的localStorage不互通,会形成缓存多份浪费。

相关文章
相关标签/搜索