注册
web

还搞不明白浏览器缓存?

一:前言


浏览器缓存浏览器储存是不一样的,友友们不要混淆,关于浏览器储存,具体可以看这篇文章 : 一篇打通浏览器储存


这里大概介绍一下:


cookieslocalStoragesessionStorageIndexedDB
服务端设置一直存在页面关闭就消失一直存在
4K5M5M无限大
自动携带在http请求头中不参与后端不参与后端不参与后端
默认不允许跨域,但可以设置可跨域可跨域可跨域

二:强缓存


强缓存是指浏览器在请求资源时,如果本地有符合条件的缓存,那么浏览器会直接使用缓存而不会向服务器发送新的请求。这可以通过设置 Cache-ControlExpires 响应头来实现。


2.1:Cache-Control 头详解


Cache-Control 是一个非常强大的HTTP头部字段,它包含多个指令,用以控制缓存的行为:



  • max-age:指定从响应生成时间开始,该资源可被缓存的最大时间(秒数)。
  • s-maxage:类似于 max-age,但仅对共享缓存(如代理服务器)有效。
  • public:表明响应可以被任何缓存存储,即使响应通常是私有的。
  • private:表明响应只能被单个用户缓存,不能被共享缓存存储。
  • no-cache:强制缓存在使用前必须先验证资源是否仍然新鲜。
  • no-store:禁止缓存该响应,每次请求都必须获取最新数据。
  • must-revalidate:一旦资源过期,必须重新验证其有效性。

例如,通过设置 Cache-Control: max-age=86400,可以告诉浏览器这个资源可以在本地缓存24小时。在这段时间内,如果再次访问相同URL,浏览器将直接使用缓存中的副本,而不与服务器通信。


2.2:Expires 头


Expires 是一个较旧的头部字段,用于设定资源过期的具体日期和时间。尽管现在推荐使用 Cache-Control,但在某些情况下,Expires 仍然是有效的。Expires 的值是一个绝对的时间点,而不是相对时间。例如:


Expires: Wed, 09 Oct 2024 18:29:00 GMT

2.3:浏览器默认行为


当用户通过地址栏直接请求资源时,浏览器通常会自动添加 Cache-Control: no-cache 到请求头中。这意味着即使资源已经存在于缓存中,浏览器也会尝试重新验证资源新鲜度,以确保用户看到的是最新的内容。


三:协商缓存


协商缓存发生在资源的缓存条目已过期设置了 no-cache 指令的情况下。这时,浏览器会向服务器发送请求,并携带上次请求时收到的一些信息,以便服务器决定是否返回完整响应或只是确认没有更新。


3.1:Last-Modified/If-Modified-Since


后端服务器可以为每个资源设置 Last-Modified 头部,表示资源最后修改的时间。当下一次请求同一资源时,浏览器会在请求头中加入 If-Modified-Since 字段,其值为上次接收到的 Last-Modified 值。服务器检查这个时间戳,如果资源自那以后没有改变,则返回304 Not Modified状态码,指示浏览器使用缓存中的版本。


3.2:ETag/If--Match


ETag 提供了一种更精确的方法来检测资源是否发生变化。它是基于文件内容计算出的一个唯一标识符。当客户端请求资源时,服务器会在响应头中提供一个 ETag 值。下次请求时,浏览器会发送 If--Match 头部,包含之前接收到的 ETag。如果资源未改变,服务器同样返回304状态码;如果有变化,则返回完整的资源及新的 ETag 值。


3.3:比较 Last-Modified 和 ETag


虽然 Last-Modified 简单易用,但它基于时间戳,可能会受到时钟同步问题的影响。相比之下,ETag 更加准确,因为它依赖于资源的实际内容。然而,ETag 计算可能需要更多的服务器处理能力。


四:缓存选择


合理的缓存策略能够显著提升网站性能和用户体验。例如,静态资源(如图片、CSS、JavaScript文件)适合设置较长的缓存时间,而动态内容则需谨慎对待,避免缓存不适当的信息。



  • 使用工具如 Chrome DevTools 来分析页面加载时间和缓存效果。
  • 对不同类型的资源设置合适的 Cache-Control 参数。
  • 注意安全性和隐私保护,确保敏感数据不会被错误地缓存。

五:使用示例



  1. 引入必要的模块:导入 http, path, fsmime 模块。
  2. 创建HTTP服务器:使用 http.createServer 创建一个HTTP服务器。
  3. 处理请求

    • 根据请求的URL生成文件路径。
    • 检查文件是否存在。
    • 如果是目录,指向该目录下的 index.html 文件。


  4. 处理协商缓存

    • 获取请求头中的 If-Modified-Since 字段。
    • 比较 If-Modified-Since 与文件的最后修改时间。


  5. 读取文件并发送响应

    • 读取文件内容。
    • 设置响应头(包括 Content-Type, Cache-Control, Last-Modified, ETag)。
    • 发送响应体。


  6. 启动服务器:监听3000端口并启动服务器。

server.js:


const http = require('http'); // 引入HTTP模块
const path = require('path'); // 引入路径处理模块
const fs = require('fs'); // 引入文件系统模块
const mime = require('mime'); // 引入MIME类型模块

// 创建一个HTTP服务器
const server = http.createServer((req, res) => {
// console.log(req.url); // /index.html // /assets/image/logo.png

// 根据请求的URL生成文件路径
let filePath = path.resolve(__dirname, path.join('www', req.url));

// 检查文件或目录是否存在
if (fs.existsSync(filePath)) {
const stats = fs.statSync(filePath); // 获取该路径对应的资源状态信息
// console.log(stats);

const isDir = stats.isDirectory(); // 判断是否是文件夹
const { ext } = path.parse(filePath); // 获取文件扩展名
if (isDir) {
// 如果是目录,则指向该目录下的 index.html 文件
filePath = path.join(filePath, 'index.html');
}

// +++++ 获取前端请求头中的if-modified-since
const timeStamp = req.headers['if-modified-since']; // 获取请求头中的 If-Modified-Since 字段
let status = 200; // 默认响应状态码为200
if (timeStamp && Number(timeStamp) === stats.mtimeMs) { // 如果 If-Modified-Since 存在且与文件最后修改时间相同
status = 304; // 设置响应状态码为304,表示资源未变更
}

// 如果不是目录且文件存在
if (!isDir && fs.existsSync(filePath)) {
const content = fs.readFileSync(filePath); // 读取文件内容
res.writeHead(status, {
'Content-type': mime.getType(ext), // 设置 Content-Type 头
'cache-control': 'max-age=86400', // 设置缓存控制为一天
// 'last-modified': stats.mtimeMs, // 资源最新修改时间(可选)
// 'etag': '由文件内容生成的hash' // 文件指纹(可选)
});
res.end(content); // 发送文件内容作为响应体
}
}

});

// 启动服务器,监听3000端口
server.listen(3000, () => {
console.log('listening on port 3000');
});r.listen(3000, () => {
console.log('listening on port 3000');
});

index.html:


<body>
<h1>midsummer</h1>
<img src="assets/image/1.png" alt="">
</body>


项目结构如下图,友友们自行准备一张图片,将项目npm init -y 初始化为后端项目,之后下载mime@3包,在终端输入npx nodemon server.js运行起来,在浏览器中查看http://localhost:3000/index.html ,观察效果。在检查中的网络里看缓存效果,同时友友们可以更改图片或者缓存方式,体验下不同的浏览器缓存方式


image.png


作者:midsummer18
来源:juejin.cn/post/7423298788873142326

0 个评论

要回复文章请先登录注册