最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 浅谈浏览器的缓存机制

    正文概述 掘金(正义de键盘侠)   2021-02-06   613

    1.按缓存位置分类

    按缓存位置分类,可以分为:Memory Cache,Disk Cache, Service Worker ,以及网络请求

    1.1Memory Cache

    memory cache 叫内存缓存,几乎所有的网络请求资源都会被浏览器自动加入到 memory cache 中。而如果极端情况下 (例如一个页面的缓存就占用了超级多的内存),那可能在 TAB 没关闭之前,排在前面的缓存就已经失效了。

    预加载(preload)请求过来的资源就会被放入 memory cache 中,供之后使用。

    memory cache 机制保证了一个页面中如果有两个相同的请求 (例如两个 src 相同的 浅谈浏览器的缓存机制,两个 href 相同的 )都实际只会被请求最多一次,避免浪费。

    不过在匹配缓存时,除了匹配完全相同的 URL 之外,还会比对他们的类型,CORS 中的域名规则等。

    因此一个作为脚本 (script) 类型被缓存的资源是不能用在图片 (image) 类型的请求中的,即便他们 src 相等。 

    如果想让 memory cache 也不存储,那就需要在 Http 请求头设置 no-store。

    1.2Disk Cache (http缓存)

    disk cache 也叫 HTTP cache,是磁盘缓存。它允许相同的资源在跨会话,甚至跨站点的情况下使用,例如两个站点都使用了同一张图片。

    disk cache 会严格根据 HTTP 头部中的各类字段来进行缓存。当命中缓存之后,浏览器会从硬盘中读取资源,虽然比起从内存中读取慢了一些,但比起网络请求还是快了不少的。绝大部分的缓存都来自 disk cache。

    凡是持久性存储都会面临容量增长的问题,disk cache 也不例外。浏览器会根据自身算法自动清理“最老的”或者“最可能过时的”资源。

    1.3Service Worker

    上述的缓存策略以及缓存/读取/失效的动作都是由浏览器内部判断和进行的,我们只能设置响应头的某些字段来告诉浏览器,而不能自己操作。

    但 Service Worker 的出现,给予了我们另外一种更加灵活,更加直接的操作方式。我们可以选择缓存哪些文件,路由匹配规则,缓存匹配并返回。

    Service Worker 借鉴了 Web Worker的 思路,即让 JS 运行在主线程之外,由于它脱离了浏览器的窗体,因此无法直接访问

    DOM。虽然如此,但它仍然能帮助我们完成很多有用的功能,比如离线缓存、消息推送和网络代理等功能。其中的离线缓存就是 Service Worker Cache

    Service Worker 能够操作的缓存是有别于浏览器内部的 memory cache 或者 disk cache 的。我们可以在 Chrome 开发者工具,Application -> Cache Storage 找到缓存的位置。这个缓存是永久性的,即关闭 TAB 或者浏览器,下次打开依然还在。有两种情况会导致这个缓存中的资源被清除:手动调用 API cache.delete(resource) 或者容量超过限制,被浏览器全部清空。

    如果 Service Worker 没能命中缓存,一般情况会使用 fetch() 方法继续获取资源。这时候,浏览器就去 memory cache 或者 disk cache 进行下一次找缓存的工作了。

    1.4查找资源的优先级

    ServiceWorker ----> memory cache ---------> disk cache ---------> 发送请求

    1.5如何查看数据是否来自缓存?

    使用google浏览器

    浅谈浏览器的缓存机制

    2.重点http缓存

    浏览器有个缓存数据库,这个数据库是为http缓存服务的,当请求的数据被缓存过,那么请求的数据直接从缓存数据库拿取。

    http缓存分为强缓存与协商缓存

    2.1强缓存

    浏览器第一次请求的数据被服务器设置成有强缓存时间的数据,那么浏览器第二次请求的时候,如果时间未过期,那么请求将不会发送到服务器,数据直接从浏览器缓存数据库获取。(从google浏览器可以看到是from disk cache)

    2.1.1设置的方法:

    响应头中设置 Expires

    Expires: Thu, 10 Nov 2017 08:45:11 GMT    // gmt 绝对时间
    

    如果跟 cache-control 的 max-age 同时存在,Expires 会被 max-age 覆盖 。 http1.1已经把它抛弃了,基本没用了。

    响应头中设置 Cache-control

    Cache-Control: max-age=2592000

    表示缓存内容将在t秒后失效(以秒为单位),在该时间内,客户端不需要向服务器发送请求。
    

    Cache-Control: no-cache

    可以在本地和代理服务器缓存,但是这个缓存需要服务器验证才可以使用,即直接进入协商缓存阶段。
    

    Cache-Control: no-store

    真正意义上的“不要缓存”,不进行任何形式的缓存,每次都从服务器获取
    

    Cache-Control: private

    客户端可以缓存,代理服务器不能缓存。例如,用户的浏览器可以缓存包含用户私人信息的HTML网页,但CDN不能缓存
    

    Cache-Control: public

    客户端和代理服务器都可以缓存
    

    Cache-Control: must-revalidate

    must-revalidate告诉缓存,在事先没有跟原始服务器进行再验证的情况下,不能提供这个对象的陈旧副本,缓存仍然可以随意提供新鲜的副本。如果在缓存进行must-revalidate新鲜度检查时,原始服务器不可用,缓存就必须返回一条504错误。
    

    Cache-Control: s-maxage

    s-maxage是针对代理服务器的缓存时间
    

    2.1.2实践代码

    const express = require('express');const app = express();const port = 8080;const fs = require('fs');const path = require('path');const moment = require('moment');app.get('/',(req,res) => {res.send(`<!DOCTYPE html><html lang="en"><head><title>Document</title></head><body>Http Cache Demo<input type='button' onclick='getData()' value='获取数据'><script src="/demo.js"></script><script >function getData(){const xhr = new XMLHttpRequest()xhr.onreadystatechange = () => {if (xhr.readystate == 4) {if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {alert(xhr.responseText)} else {alert("Request was unsuccessful: " + xhr.status)}}}xhr.open("get", "/demo1.js", true)xhr.send(null)}</script></body></html>`)})function getGLNZ(){  return moment().utc().add(2,'m').format('ddd, DD MMM YYYY HH:mm:ss')+' GMT';}app.get('/demo1.js',(req, res)=>{  let jsPath = path.resolve(__dirname,'./static/js/demo1.js');  let cont = fs.readFileSync(jsPath);  res.setHeader('Cache-Control', 'public')  res.setHeader('Cache-Control', 'max-age=31536000')  console.log(123)  res.end(cont)})app.listen(port,()=>{  console.log(`listen on ${port}`)})
    

    结果:

    浅谈浏览器的缓存机制

    2.2协商缓存

    当强缓存的时间过期了,但是服务器的资源并没有发生改变,那么服务器就需要发响应数据的内容给浏览器了,只需要发状态码为304的响应头告诉浏览器继续去缓存数据库拿数据。

    2.2.1设置的方法:

    方法1: 服务器 Last-Modified 浏览器 If-Modified-Since

    具体流程如下:客户端第一次向服务器发起请求,服务器将最后的修改日期(Last-Modified)附加到所提供的资源上去当再一次请求资源时,如果没有命中强缓存,在执行再验证时,会包含一个If-Modifed-Since首部,值为资源的 Last-Modified 日期,询问服务器该资源自从这个 Last-Modified 日期之后有没有被修改过。如果内容被修改了,服务器回送新的资源,返回200状态码和最新的修改日期如果内容没有被修改,会返回一个304 Not Modified响应
    

    方法2:服务器ETag 浏览器If-None-Match

    具体流程和 If-Modified-Since 一致,只是 Last-Modified 字段和它所表示的更新时间改变成了 Etag 字段和它所表示的文件 hash,把 If-Modified-Since 变成了 If-None-Match。服务器对比已缓存标签与服务器文档中的标签是否有所不同,相同返回 304, 不相同返回新资源和 200。
    

    以上默认设置都是基于express框架

    2.2.2实际代码

    const express = require('express');const app = express();const port = 8080;const fs = require('fs');const path = require('path');const moment = require('moment');app.get('/',(req,res) => {res.send(`<!DOCTYPE html><html lang="en"><head><title>Document</title></head><body>Http Cache Demo<input type='button' onclick='getData()' value='获取数据'><script src="/demo.js"></script><script >function getData(){const xhr = new XMLHttpRequest()xhr.onreadystatechange = () => {if (xhr.readystate == 4) {if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {alert(xhr.responseText)} else {alert("Request was unsuccessful: " + xhr.status)}}}xhr.open("get", "/demo2.js", true)xhr.send(null)}</script></body></html>`)})function getGLNZ(){return moment().utc().add(2,'m').format('ddd, DD MMM YYYY HH:mm:ss')+' GMT';}app.get('/demo2.js',(req, res)=>{  let jsPath = path.resolve(__dirname,'./static/js/demo1.js');  let cont = fs.readFileSync(jsPath);  let status = fs.statSync(jsPath)  let lastModified = status.mtime.toUTCString()  if(lastModified === req.headers['if-modified-since']){   res.writeHead(304, 'Not Modified')   res.end()  } else {  res.setHeader('Cache-Control', 'public')  res.setHeader('Cache-Control', 'max-age=5')  res.setHeader('Last-Modified', lastModified)  res.writeHead(200, 'OK')  res.end(cont)}})app.listen(port,()=>{console.log(`listen on ${port}`)})
    

    浅谈浏览器的缓存机制

    3.更新和废弃缓存的方法

    将资源文件更改成hash名称,迫使请求路径发生变化,从而开始下载新的资源。

    4.缓存应用

    不常变化的资源

    Cache-Control: max-age=31536000
    

    经常变化的资源

    Cache-Control: no-cache
    

    5.参考资料来源

    blog.csdn.net/guduyibeizi…
    juejin.im/post/684490…


    起源地下载网 » 浅谈浏览器的缓存机制

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元