合理利用浏览器缓存

拓朴沙漏
• 阅读 3900

合理利用缓存
概述:本章主要讨论了两方面的内容。1. 浏览器缓存机制。 2. web实践中如何有效利用这些缓存
浏览器缓存机制

作为web开发人员经常遇到的问题之一就是我明明修复并且部署了这个BUG为什么线上有的用户还会出现这个问题呢?还有每次更新完我们都会说你清除缓存试试?为什么一定要清除缓存呢,可以肯定说绝大部分用户是不知道要清除缓存的!那我们能否不清除缓存,最新部署的文件能够马上就生效呢。答案是肯定的,这就需要我们花费一点时间了解一下缓存是怎么工作的。
我们可以简单的理解为缓存是为了减少网络带宽和优化用户体验而存在的。核心就是把缓存的内容保存在了本地,而不用每次都向服务端发送相同的请求,设想下每次都打开相同的页面,而在第一次打开的同时,将下载的js、css、图片等“保存”在了本地,而之后的请求每次都在本地读取,效率是不是高了很多。当我用浏览器打开一个网页可以发现浏览器加载页面资源的http请求返回的Status Code有以下常见的值304 Not Modified/200 OK (from disk cache)/ 200 OK。这些值代表着什么意思呢?其实浏览器就是依靠请求和响应中的的头信息来控制缓存的。下面我们来具体分析一下。
当我们第一次(或者ctrl+F5)打开百度,我们会发现加载jquery.js的http请求响应字段如下

合理利用浏览器缓存

由于是第一次或者强制刷新打开的,所以浏览器会忽略缓存,直接向服务器发送请求加载资源,图中画框的那几个字段是与缓存相关的。它们的意义如下:

1. cache-control:max-age=315360000:它告诉浏览器这个资源的缓存时间为315360000秒(10年),那么浏览器就将这个文件保存到本地磁盘缓存起来,下次你再次打开百度时,只要是再10年内浏览器就不向服务器发送请求加载资源了,而是直接从缓存中加载。
2. expires:Fri, 06 Nov 2026 04:20:09 GMT:它告诉浏览器这个资源的有效期:现在-->2026年11月6号04:20:09,在这个时间内你打开百度浏览器就不向服务器发送请求加载资源了,而是直接从缓存中加载。

这个是不是与cache-control功能有点重合呢,是的!Expires是HTTP1.0的东西,而Cache-Control是HTTP1.1的,规定如果max-age和Expires同时存在,前者优先级高于后者。Cache-Control的参数可以设置很多值,譬如(参考浏览器缓存机制)。

3. Last-Modified: Mon, 07 Nov 2016 07:51:11 GMT:标示这个响应资源的最后修改时间。
4. ETag: 告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器觉得)

当我按下F5重新加载页面时会得到下面的http请求响应信息

合理利用浏览器缓存

我们会发现浏览器是发送了一个http请求而不是我们之前说的在10年之内不发送请求,并且这个请求的响应是304,就是说当我按下F5时,浏览器忽略了上次请求返回的cache-control和expires字段的值,它是再次发送了一个获取资源的请求,但是这次http请求头部包含了两个新字段If-Modified-Since和If-None-Match(这两个字段的值就是上次请求资源响应中包含的Last-Modified和ETag的值),这就是问题所在,服务器检测到这两个字段做对应的响应如下:
If-Modified-Since:服务器收到请求后发现有头If-Modified-Since则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省加载时间与带宽),告知浏览器继续使用所保存的cache。
If-None-Match: 服务器收到请求后发现有If-None-Match则与被请求资源的相应校验串进行比对,决定返回200或304。

我们会发现这两个字段功能也有点重合,原因如下:
1) 次Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间。
2) 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存。
3) 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

那现在就还剩下一个问题,就是当我按下F5时,浏览器为什么不是直接从本地缓存中加载文件而是发送了一个http请求呢?这个是就用户行为与浏览器对缓存的控制有关

合理利用浏览器缓存

缓存总结如下
浏览器第一次请求:

合理利用浏览器缓存

浏览器再次请求时:

合理利用浏览器缓存

有效利用缓存
下面我们就来说说WEB资源文件的缓存时间设置为多少是全适的呢。

现在大部分网站都是每次更新部署时,只要有修改的文件都会重新生成一个名字(如:gulp打包[http://www.xxx.tv/dist/hr20170117/js/main-f3d7137ecb.js],HTML文件除外),相当于有更改的文件都有新的URL.针对这种情况,我们可以进行如下设置
  1. HTML文件可以设置为max-age为0,那么用户每次打开网页都会向服务器询问这个网页有没有更改,如果有更改用户就能够加载最新的文件。

  2. CSS/JS文件可以设置为30天或者1年。
    下面为对应的nginx配置
    location ~ .*.(js|css)?${

    expires 1M;

    }

  3. ~* .(?:manifest|appcache|html?|xml|json)$ {

expires -1;
}

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Http 缓存策略
1)浏览器缓存策略浏览器每次发起请求时,先在本地缓存中查找结果以及缓存标识,根据缓存标识来判断是否使用本地缓存。如果缓存有效,则使用本地缓存;否则,则向服务器发起请求并携带缓存标识。根据是否需向服务器发起HTTP请求,将缓存过程划分为两个部分:强制缓存和协商缓存,强缓优先于协商缓存。强缓存,服务器通知浏览器一个缓存时间,在
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这