JavaScript 页面缓存

1.前言

  • 由来:默认环境中,当浏览器重复访问一个资源时,为节省资源与性能,浏览器将其缓存,后续的请求不再从服务器下载该资源,而是直接从本地缓存中读取,默认时没有强制缓存的
  • 副作用:当服务器资源更新时,浏览器无法得知,依旧加载的是旧资源
  • 缓存类型:强制缓存和协商缓存

2.强制缓存

  • 作用:告诉浏览器,强制缓存生效期间,再次拿当前资源不要发请求,直接读取磁盘
  • 通过 Expires 设定缓存的过期时间,这个时间是服务器设定的,但是如果客户端与服务端时间不同步,就会产生问题,所以不推荐使用,现在已被后面的 Cache-Control 替代
//强制缓存(设置过期时间)
var expires = new Date()
//1分钟过期
expires.setMinutes(expires.getMinutes() + 1)
res.setHeader('Expires', expires.toUTCString())

  • 通过 Cache-Control 设定缓存有效时长(秒),以客户端时间为准,往后计算缓存有效期
res.setHeader("Cache-Control","max-age=7200")

3.协商缓存

  • 说明:顾名思义,就是在使用本地缓存之前,向服务器发起GET请求,与之协商当前的缓存是否已经过期,如果已经过期,则下载最新的资源,如果没过期,则读取缓存
  • 原理:资源缓存时,附带一个标识(文件最终修改时间,或者文件内容hash),下次请求时然后拿这个标识与服务器的标识 做对比,如果不一致,则返回最新资源,如果一直,则返回返回状态码 304,让浏览器读本地缓存
  • 注意:需要设定 Cache-Control 为 no-cache (这里的no-cache含义并不是说不要缓存,而说的是协商缓存,只有设定为no-store才是禁用缓存,设置 max-age 也是可以启用缓存的,只不过此时强制换成优先级比协商缓存高)
  • last-modified:通过获取文件最终修改时间作为标识进行判断,下一次请求时,请求头会自动添加 "if-modified-since" 字段并带上之前返回的last-modified的值,服务器就可以知道当前资源的最终修改时间,以此来判断返回的内容。这种方式有2个弊端:第一,文件可能被动过,但是里面内容没变,可能只是重命名,第二,修改时间戳精确到秒,做不到毫秒级的识别判定
//获取文件
var data = fs.readFileSync('./www/index.js')
//获取文件时间
var {mtime} = fs.statSync('./www/index.js')
//设置最终修改时间
res.setHeader("last-modified", mtime.toUTCString())
//开启协商缓存
res.setHeader('Cache-Control','no-cache')

//对比协商缓存的时间,来确定返回结果
var ifModifiedSince = req.headers["if-modified-since"]
if(ifModifiedSince == mtime.toUTCString()){
	//告诉浏览器资源未发生变化,让他读缓存
	res.statusCode = 304
	res.end()
}else{
	//返回图片
	res.end(data)
}



  • Etag:通过文件内容进行hash运算生成字符串(hash运算使用的包名叫 etag),以此带代替last-modified,下一次请求时,请求头会自动添加 "If-None-Match" 字段并带上之前返回的Etag的值。缺点是hash运算计算开销大,影响性能
//获取文件
var data = fs.readFileSync('./www/index.js')
//hash运算生成字符串
var etagContent = etag(data)
//添加到响应头
res.setHeader('etag',etagContent)
//开启协商缓存
res.setHeader('Cache-Control','no-cache')

//判断内容是否发生变化
var ifNoneMatch = req.headers["if-none-match"]
if(ifNoneMatch == etagContent){
	//告诉浏览器资源未发生变化,让他读缓存
	res.statusCode = 304
	res.end()
}else{
	//返回图片
	res.end(data)
}


4.缓存策略

  • HTML文件:HTML文件包含了很多资源的引用,推荐使用协商缓存,当文件修改时才获取最新版本
  • 图片,字体文件等静态资源:这类资源要么不改,要么会整体替换掉,推荐使用强制缓存,但是要注意缓存的时间,缓存的东西太多客户端有压力
  • 固定URL的js,css文件:这类文件修改频繁,推荐使用协商缓存,当文件修改时才获取最新版本
  • 编译后的js,css文件:这里文件常见于脚手架项目,打包编译后文件名是随机变动的,和图片类似,推荐使用强制缓存

5.动态资源链接

  • 原理:当一个请求路径不变,但是携带的参数发生变化时,浏览器视为新请求,不读取缓存数据
//在资源链接后面添加版本号(v=100),修改通过这个版本号(v=101),强制客户端更新资源
<script src="./index.js?v=100"></script>
  • 全局控制:对资源链接的版本号进行动态拼接,只要修改系统版本号,所有资源强制升级

6.手动清除缓存

  • F12->网络->选中请求->清除缓存
  • 页面强制重载

7.meta标签中的Cache-Control

  • 语法
<meta http-equiv="Cache-Control" content="no-cache">
  • 说明:meta标签在HTML文档中用于向浏览器提供关于如何缓存文档的指令。然而,这些指令并不总是被所有浏览器遵循,因为它们的实现可能因浏览器而异。这些指令通常只影响对HTML文档的缓存决策,而不是文档中包含的资源(如CSS、JavaScript文件或图片)的缓存
  • 对比HTTP的Cache-Control:HTTP响应头中的Cache-Control指令是由服务器发送的,用于精确控制浏览器(以及其他HTTP缓存)对响应的缓存方式。这些指令对于所有类型的资源(HTML文档、CSS、JavaScript、图片等)都有效,由于HTTP响应头是由服务器直接发送给浏览器的,因此这些指令通常具有比HTML文档中的标签更高的优先级。浏览器在决定是否缓存资源时,会优先考虑HTTP响应头中的Cache-Control指令。

8.离线浏览

  • 使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本
  • manifest 的技术已被 web 标准废弃,不再推荐使用此功能
posted @ 2024-03-22 14:36  ---空白---  阅读(13)  评论(0编辑  收藏  举报