“这个页面你改了吗,怎么还是没变?”
“那你清一下缓存看看!”
在开发中我们经常会听到这样的对话,
那么浏览器缓存到底是什么? 他又是如何对文档进行存储的呢?
一、什么是浏览器缓存
简单来说,浏览器缓存就是将页面上的一些文件储存在本地磁盘中,以便下次再打开这个地址的时候快速加载页面,减少请求资源。
用chrome打开我们的付呗官网,查看network
刷新页面后,我们看到有些js,图片,css的size变成了form memory cache,form disk cache 这又代表什么呢
在network的size栏通常会有三种状态:
-
form memory cache
-
form disk cache
-
资源本身大小
form memory chache:在内存中获取资源,不会请求服务器,关闭浏览器后,数据将不存在,一般js,图片,字体会存在内存中。
form disk cache:这个资源是在磁盘中获取的,也不会请求服务器,关闭浏览器后,数据依然存在,一般非脚本会存在硬盘中,如css
资源本身大小:当http状态为200时,是从服务器获取的资源,当http为304时,size里面的数字是与服务器端通信报文的大小,不是资源本身的大小,这个时候这个资源是从本地获取的。
form memory chache 与 form disk cache的区别
当关闭浏览器时,内存中的数据会被清空,而磁盘中的数据不会,所以当再次打开浏览器时,仍可以从磁盘中获取,而内存中的数据则不行
三级缓存原理
-
内存 -> 硬盘 -> 请求服务器
http header
点击一个缓存了的文件,我们来看一下这个文件的headers
Response Headers头:
在http中,控制缓存开关的字段有两个:Pragam 和 Cache-control。
-
Pragam
Param有两个字段,Pargam和Expires,
当Pargam的值为no-cache时,表示禁止缓存。
Expires的值为一个GMT时间,表示该缓存的有效时间。
-
Cache-control
cache-control用于指定缓存指令,所有请求/响应的缓存机制都要遵循这个指令。
下面是cache-control的一些可能值:
指令 | 作用 |
public | 表示响应可以被任何缓存所缓存,默认为public |
private | 响应只作为私有的缓存,不能在用户间共享 |
no-cache | 指定不缓存响应 |
no-store | 绝对禁止缓存,优先级最高 |
max-age | 设置缓存的最大有效时间,单位为(s) |
s-maxage | 只用于共享缓存,比如CDN缓存,与max-age 的区别是:max-age用于普通缓存, 而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖max-age 和 Expires |
must-revalidate | 如果页面过期,则去服务器进行获取 |
强缓存与协商缓存
下面这两张图,可以很好地说明缓存的流程。
当浏览器第一次请求时:
第一次请求时浏览器会记住响应头的Last-Modified和Etag。
服务器会将页面最后修改时间通过Last-Modified标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个Etag,并发送给客户端。
此时的状态为200
再一次请求:
①ETag: 是HEAD中的一个属性,服务器请求资源时,算出一个哈希值并通过Etag返回给浏览器,浏览器把哈希值和请求的资源存储在本地,其实就是一个文件标识。
②Last-Modifiedl:服务器上修改文件的最后时间
③If-None-Match,④If-Modified-Since : 服务器检查参数值,如果文件没有改变则返回304
浏览器会携带保存的Last-Modified和Etag分别作为If-Modified-Since和If-None-Match放入请求头中携带过去,以此到服务端验证此次请求的资源是否过期或更新;服务端进行判断,若过期或更新,则返回新的资源,否则返回空即可,节省服务端消耗。
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码;
协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;
两者的共同点是,都是从客户端缓存中读取资源;区别是强缓存不会发请求,协商缓存会发请求。
那么如何不再缓存资源?
-
设置html的meta标签(此方法对js与css无效果)
-
<meta http-equiv="expires" content="0"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache">
-
插入时间戳,使每次请求的参数不同
-
var getTimestamp = new Date().getTime(); <img src="1.png?t=' + getTimestamp'">
-
与时间戳方法同理,也可以插入随机数
-
<img src="1.png?' + Math.random()'">
-
webpack配置缓存
-
// webpack.config.js module.exports = { entry: "main.js", output: { path: "/build", filename: "main.[hash].js" } };
通过hash占位符,在每次生成打包文件时,都会通过文件内容生成唯一的hash,并添加到输出的文件名中。如果有多个入口文件,可以使用name占位符设置输出:
// webpack.config.js
module.exports = {
entry: {
main:"main.js",
sub:"sub.js"
},
output: {
path: "/dist",
filename: "[name].[hash].js"
}
};