zoukankan      html  css  js  c++  java
  • 前端静态资源的缓存和更新问题解析

    浏览器缓存主要有两类 
    缓存协商:Last-midified ,Etag 
    彻底缓存:cache-control,Expires 

      缓存协商的意思是需要去服务器端询问页面有没有修改过,没有修改过则返回304直接使用缓存内容,否则返回新内容 
    协商步骤: 

    1、服务器发送带Last-midified:GMTtime 头的http response

    2、浏览器下次请求时带上if-modified-since:GMTtime http 请求头

    3、服务端用本地Last-midified时间与if-modified-since比较,计算浏览器数据是否过期并发送响应

    Etag的工作原理与Last-midified类似,不同点在于Etag的值是用户可自定义的 

      彻底缓存的意思是在缓存失效之前不再需要跟服务器交互

    常用的是Expires,Expires的值是一个绝对时间,由服务器产生 这儿存在一个问题,就是服务器的时间可能给客户端的时间不一致导致缓存时间的偏差

    要解决这个问题就要使用cache-control,它保存的是一个相对浏览器的时间

    如果同时存在cache-control和Expires怎么办呢? 浏览器总是优先使用cache-control,如果没有cache-control才考虑Expires 

    expire:
    如果apache开启了expire模块, 当浏览器发送该资源请求的时候, apache返回资源的同时,会返回一个名为expire的http头,expire头的内容是一个时间值, 这一个值就是资源在本地的过期时间, 这个值会存在本地.
    也就是说,在本地缓存阶段,在本地找到了一个对应的资源值,而且当前时间还没超过资源的过期时间, 那么就直接使用这一个资源,不会发送http请求.

    cache-control:
    cache-control是http协议中常用的头部之一,顾名思义, 他是负责控制页面的缓存机制,如果该头部指示缓存, 缓存的内容也会存在本地, 操作流程和expire相似,但也有不同的地方, cache-control有更多的选项, 而且也有更多的处理方式.

    if-modified-since 和 last-modified:
    当apache接收到一个资源请求(假设是用户是第一次访问,没有任何缓存), 服务器返回资源的同时,还会发送一个last-modified的http响应头, last-modified响应头的内容值是该资源在服务器上最后修改的时间.浏览器接受到这个http头后,会
    把其内容值和资源同时保存起来.
    当用户第二发送资源请求(假设这里expire没有生效或者已经过期), 浏览器在本地找到了一个相同的资源,但是不能确定该资源是否和服务器上的一样(有可能在两次访问期间,服务器上的资源已经被修改过),此时浏览器发送请求的时候,请求头内会
    附带一个if-modified-since的请求头, 这个头部的内容就是上一次last-modified返回的值, 服务器把这个头的值和请求资源的最后修改时间对比,如果两个值相同,则认为资源没有修改,将会返回304,让浏览器使用本地资源.否则服务器将返回资源,而且
    返回200状态

    if-none-match 和 etag:
    其实这两个头部和if-modified-since, last-modified的工作原理是一样的, if-none-match作为请求头, etag作为响应头.既然工作原理一样, 为什么etag这对头部会出现呢?
    原因在于, last-modified请求头的内容是以文件最后修改的时间作为对比的,但是unix系统里面, 文件修改的时间只保存到了秒. 如果某些应用内存在1秒内对文件做了多次修改,这样last-modified是不能完成比较功能的.所以要引入一个新的机制(原因可能不止这一个);
    etag的值一般由3个数值组成,资源的inode值, 最后修改时间, 资源大小,以16进制组成一个字符串, 例如:1a-182b-10f; 但这个格式不是固定的, 只要保证该值的唯一性,但不限格式.

    静态资源的更新:张云龙老师的blog写的很好移步这里

    html5离线存储

    步骤:

    1、配置apache让apache支持manifest文件

    2、创建manifest文件test.manifest

    1 CACHE MANIFEST  # wanz app v1     
    2 # 指明缓存入口(指明需要缓存的文件)  
    3 CACHE:  index.html  style.css  images/logo.png  scripts/main.js     # 以下资源必须在线访问  
    4 NETWORK:  login.php     
    5 # 如果index.php无法访问则用404.html代替  
    6 FALLBACK:  /index.php /404.html

    3、关联manifest文件到html文档

     1 <html manifest="test.manifest"> ... </html> 

    注意:#是用来注释一行的,但它还有一个小作用,web应用的缓存只有在manifest文件被修改的情况下才会被更新,所以如果你只是修改了被缓存的文件,那么用户本地的缓存还是不会被更新的,但是你可以通过修改manifest文件来告诉浏览器需要更新缓存了。利用这点,你可以像上面的例子中那样,写一句这样的注释一个文件版本:

    # wanz app v1

    优点:你可以很明确的了解离线web应用的版本
       通过简单的修改这个版本号就可以轻易的通知浏览器更新
       你可以配合JavaScript程序来完成缓存更新

    CACHE:
    这个是manifest文件的默认入口,在此入口之后罗列的文件 (或直接写在CACHE MANIFEST后的文件)在它们下载到本地后会被缓存起来
    NETWORK:
    可选的,在此节后面所罗列的文件是需要访问网络的,即使用户离线访问了也会直接跳过缓存而访问服务器
    FALLBACK:
    可选的,用来指定资源无法访问时的回调页面。每一行包括两个URI,第一个是资源文件URI,第二个是回调页面URI。

    html5缓存的更新问题:

    方法有三种:

    1、用户清除了离线存储的数据,这个不一定就是清理浏览器历史记录就可以做到的,因为不同浏览器管理离线存储的方式不同。比如Firefox的离线存储数据要到“选项”=>“高级”=>“网络”=>“脱机存储”里才可以清除。
    2、manifest文件被修改,上面说的,你修改了manifest文件里所罗列的文件也不会更新缓存,而是要替换manifest文件//修改注释更新# wanz app v1
    3、使用JavaScript api编写更新程序

    方法12为自动更新,方法3为手动更新

    1 var appCache = window.applicationCache;     
    2 appCache.update(); // 开始更新     
    3 if (appCache.status == window.applicationCache.UPDATEREADY) {    
      appCache.swapCache(); // 得到最新版本缓存列表,并且成功下载资源,更新缓存到最新
    }
  • 相关阅读:
    eth私有节点搭建
    angularjs 文件类型格式校验
    Windows Server 2019, 2016 or 2012 安装telnet
    Oracle导致Redo日志暴增的SQL语句排查
    log4j waf 绕过技巧
    jtemplate使用笔记
    NPOI2.0
    关于java同一个类互相调用,spring事务失效问题
    java 将redis的数据批量取出来的时候遇到json格式转换异常
    超级好用的文档转换工具
  • 原文地址:https://www.cnblogs.com/cdwp8/p/4062790.html
Copyright © 2011-2022 走看看