浏览器缓存
loyalvi Lv7

浏览器缓存

浏览器缓存

浏览器缓存机制是一种优化网站性能和用户体验的技术,它允许浏览器存储网页资源的副本,以便在后续的访问中可以直接从本地加载,而不需要重新从服务器下载。这种机制可以减少网络延迟、节省带宽,并提高页面加载速度。浏览器缓存可以分为以下几个部分:

  1. 浏览器缓存流程
    • 请求阶段:当浏览器请求一个资源时,会首先检查本地缓存是否有该资源的副本。
    • 匹配阶段:如果本地有缓存,浏览器会检查缓存的有效期和相关性。
    • 验证阶段:如果缓存已过期或需要验证,浏览器会向服务器发送请求,询问资源是否有更新。
    • 更新阶段:服务器响应请求,如果资源未更改,则返回304状态码,告诉浏览器可以使用本地缓存;如果资源已更改,则返回新资源和200状态码。
  2. 强缓存(HTTP 200 from Cache)
    • 通过 Cache-ControlExpires 头来控制。
    • Cache-Control 提供了多种指令,如 no-cacheno-storemax-age 等,用于控制资源的缓存行为。
    • Expires 指定资源过期的具体日期和时间,但不如 Cache-Control 灵活。
  3. 协商缓存(HTTP 304 Not Modified)
    • 当强缓存失效后,浏览器会发送带有条件请求的HTTP请求。
    • 使用 If-Modified-SinceLast-ModifiedIf-None-MatchETag 来实现。
    • If-Modified-SinceLast-Modified 基于时间戳,If-None-MatchETag 基于资源的特定标识符。
  4. ETag 和 If-None-Match
    • ETag 是服务器响应头中的一个字段,它提供了一个资源的唯一标识符。
    • If-None-Match 是浏览器请求头中的一个字段,携带上次请求中服务器返回的 ETag 值。
    • 如果 ETag 没有变化,服务器返回304状态码,告诉浏览器资源未更改,可以使用缓存副本。
  5. 缓存位置
    • 内存缓存:最快的缓存类型,但可能因为浏览器关闭而丢失。
    • 磁盘缓存:存储在硬盘上,容量更大,持久性更强。
  6. 缓存策略
    • 开发者可以通过设置HTTP头来控制缓存行为,选择合适的缓存策略可以显著提高网站性能。
  7. 清除缓存
    • 用户或开发者可以手动清除浏览器缓存,以确保获取最新的资源。
  8. 缓存与SEO
    • 合理使用缓存可以提高网站对搜索引擎的友好性,但也需要确保搜索引擎能够获取到最新的内容。
      浏览器缓存机制是一个复杂但高效的系统,它涉及到客户端和服务器端的多个组件,合理配置和使用缓存可以显著提升网站的性能和用户体验。

强缓存和协商缓存

强缓存和协商缓存是Web开发中用于提高资源加载效率和减少服务器负载的两种缓存机制。它们各自有不同的工作方式和适用场景:

强缓存(HTTP 200 From Cache)

强缓存是指浏览器在不与服务器通信的情况下,直接从本地缓存中读取资源的过程。如果资源有效并且没有过期,浏览器将使用本地缓存的副本,而不是从服务器重新下载资源。强缓存主要依赖于以下HTTP头:

  1. Cache-Control
    • Cache-Control 是最重要的HTTP缓存头之一,它提供了多种指令来控制资源的缓存行为。
    • max-age=<seconds>:指定资源能够被缓存的最大时间(以秒为单位)。
    • no-cache:指示必须先向服务器确认资源是否更新,才能从缓存读取资源。
    • no-store:指示不应该缓存请求或响应的任何部分。
    • public:响应可以被任何中间缓存存储。
    • private:响应是为单个用户准备的,只能被客户端缓存。
  2. Expires
    • Expires 指定资源过期的具体日期和时间。
    • 它是一个绝对时间,而 Cache-Controlmax-age 是一个相对时间。

协商缓存(HTTP 304 Not Modified)

当强缓存失效(即资源已过期或被配置为 no-cache)时,浏览器将使用协商缓存来决定是否需要从服务器重新获取资源。协商缓存依赖于服务器来验证资源是否自上次请求以来发生了变化:

  1. Last-Modified / If-Modified-Since
    • Last-Modified:服务器在响应中包含这个头,指示资源的最后修改时间。
    • If-Modified-Since:在随后的请求中,浏览器会包含这个头,并携带之前 Last-Modified 的值,询问服务器自那个时间以来资源是否被修改过。
  2. ETag / If-None-Match
    • ETag(Entity Tag):服务器在响应中包含这个头,提供一个资源的唯一标识符,通常是资源的哈希值。
    • If-None-Match:在随后的请求中,浏览器会包含这个头,并携带之前 ETag 的值,询问服务器资源是否发生了变化。

工作流程对比

  • 强缓存
    1. 浏览器请求资源。
    2. 服务器响应资源,并包含缓存控制头(如 Cache-ControlExpires)。
    3. 浏览器存储资源和缓存头。
    4. 后续请求时,浏览器检查本地缓存和缓存头,如果资源未过期且符合缓存规则,直接使用缓存。
  • 协商缓存
    1. 浏览器请求资源。
    2. 服务器响应资源,并包含缓存控制头和验证头(如 Last-ModifiedETag)。
    3. 浏览器存储资源和所有相关的头。
    4. 后续请求时,浏览器检查本地缓存,如果资源已过期或被标记为 no-cache,浏览器会发送带有验证头的请求。
    5. 服务器检查验证头,如果资源未更改,返回304状态码;如果资源已更改,返回新资源和200状态码。
      通过合理配置强缓存和协商缓存,可以显著提高网站的性能,减少不必要的网络请求,加快页面加载速度。

禁用浏览器缓存

禁用浏览器缓存可以通过以下几种方法实现:

  1. 开发者工具禁用缓存
    • 打开浏览器的开发者工具(通常可以通过按 F12Ctrl+Shift+I(Windows/Linux)或 Cmd+Opt+I(Mac)打开)。
    • 转到“网络”(Network)标签页。
    • 勾选“禁用缓存”(Disable cache)选项。这样,在开发者工具打开的情况下,浏览器会忽略缓存并从服务器重新加载资源。
  2. 使用Meta标签
    • 在HTML文档的 <head> 部分,可以添加以下meta标签来防止页面被缓存:
      1
      2
      3
      <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
      <meta http-equiv="Pragma" content="no-cache" />
      <meta http-equiv="Expires" content="0" />
    • 这些标签告诉浏览器不缓存页面内容,每次访问时都从服务器获取最新版本。
  3. 浏览器设置
    • 在某些浏览器中,你可以直接在设置中禁用缓存。例如,在Firefox中可以通过进入 about:config 页面,搜索并设置 network.http.use-cachefalse
  4. 使用Chrome扩展程序
    • 可以使用专用的Chrome扩展程序来禁用缓存。例如,Classic Cache Killer插件可以一键开启或关闭缓存。
  5. 清除浏览器缓存
    • 在Chrome浏览器中,可以通过以下步骤清除缓存:
      • 点击浏览器右上角的菜单按钮(三个竖点图标)。
      • 选择“更多工具”>“清除浏览数据”。
      • 在弹出的对话框中,选择要清除的时间范围(建议选择“全部时间”)。
      • 勾选“缓存图像和文件”选项。
      • 点击“清除数据”按钮。
  6. 修改Chrome启动参数
    • 通过更改Chrome启动参数,比如使用快捷方式,在路径末尾chrome.exe之后添加--disk-cache-size=1或者--disk-cache-dir=nul,可以达到禁用缓存的效果。
  7. Chrome Flags设置
    • 在Chrome浏览器的地址栏中输入 chrome://flags/ 进入浏览器设置页面。
    • 搜索“禁止缓存 (Disable caching of all the network requests)”选项,并将其设置为“启用 (Enabled)”状态。
    • 重启浏览器后,所有网页的缓存功能将被禁用。
      请注意,禁用缓存可能会导致访问速度变慢,因为每次访问页面都需要重新获取最新的数据。同时,禁用缓存还可能在一定程度上增加服务器的负担,因此需要根据实际需求进行设置。

缓存的存取

在JavaScript中,可以通过多种方式实现缓存的存取,常见的缓存方式包括浏览器缓存(如Cookie、localStorage、sessionStorage、IndexedDB等)和内存缓存。以下是这些缓存方式的使用方法和特点:

Cookie是存储在浏览器中的小型文本文件,通常用于存储用户会话信息等。

存储Cookie

1
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2023 12:00:00 UTC; path=/";

读取Cookie

1
2
const x = document.cookie;
console.log(x); // 输出所有Cookie

特点

  • 限制:Cookie大小有限制(通常为4KB),且每次请求都会发送到服务器。
  • 适用场景:适合存储少量数据,如用户会话信息。

2. localStorage

localStorage是HTML5提供的Web存储机制,用于存储大量数据,且数据不会过期。

存储数据

1
localStorage.setItem("username", "John Doe");

读取数据

1
2
const username = localStorage.getItem("username");
console.log(username); // 输出:John Doe

删除数据

1
2
localStorage.removeItem("username"); // 删除指定键
localStorage.clear(); // 清空所有数据

特点

  • 容量:通常可存储5MB左右。
  • 适用场景:适合存储用户偏好设置、主题切换等。

3. sessionStorage

sessionStoragelocalStorage类似,但数据仅在当前会话中有效,关闭浏览器标签页后数据会被清除。

存储数据

1
sessionStorage.setItem("sessionKey", "sessionValue");

读取数据

1
2
const sessionValue = sessionStorage.getItem("sessionKey");
console.log(sessionValue); // 输出:sessionValue

特点

  • 容量:与localStorage类似,通常为5MB。
  • 适用场景:适合存储会话级别的数据,如登录状态。

4. IndexedDB

IndexedDB是一种低级API,用于存储大量结构化数据。它是一个非关系型数据库,支持事务操作。

存储数据

1
2
3
4
5
6
7
8
9
10
11
12
13
// 打开数据库
const request = indexedDB.open("myDatabase", 1);
request.onupgradeneeded = function(event) {
const db = event.target.result;
const objectStore = db.createObjectStore("myStore", { keyPath: "id" });
objectStore.add({ id: 1, name: "John Doe" });
};
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(["myStore"], "readwrite");
const objectStore = transaction.objectStore("myStore");
objectStore.add({ id: 2, name: "Jane Doe" });
};

读取数据

1
2
3
4
5
6
7
8
9
10
const request = indexedDB.open("myDatabase", 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(["myStore"], "readonly");
const objectStore = transaction.objectStore("myStore");
const getRequest = objectStore.get(1);
getRequest.onsuccess = function(event) {
console.log(event.target.result); // 输出:{ id: 1, name: "John Doe" }
};
};

特点

  • 容量:存储容量较大,通常可达几十MB。
  • 适用场景:适合存储复杂数据结构,如离线应用。

5. Memory Cache(内存缓存)

内存缓存通常用于临时存储数据,数据存储在JavaScript的内存中,页面刷新后数据会丢失。

存储数据

1
2
const memoryCache = {};
memoryCache["key"] = "value";

读取数据

1
console.log(memoryCache["key"]); // 输出:value

特点

  • 容量:受限于浏览器内存。
  • 适用场景:适合临时存储数据,如页面级缓存。

6. Cache API

Cache API是HTML5提供的用于存储和管理HTTP请求和响应的API,主要用于实现离线功能和服务端缓存。

存储数据

1
2
3
caches.open("my-cache").then(cache => {
cache.put(new Request("https://example.com/image.jpg"), new Response(new Blob(["Hello, World!"])));
});

读取数据

1
2
3
4
5
caches.match("https://example.com/image.jpg").then(response => {
if (response) {
response.text().then(text => console.log(text)); // 输出:Hello, World!
}
});

特点

  • 适用场景:主要用于离线应用和服务端缓存。

总结

  • Cookie:适合存储少量数据,如用户会话信息。
  • localStorage:适合存储持久化数据,如用户偏好设置。
  • sessionStorage:适合存储会话级数据,如登录状态。
  • IndexedDB:适合存储复杂数据结构,如离线应用。
  • Memory Cache:适合临时存储数据,如页面级缓存。
  • Cache API:适合实现离线功能和服务端缓存。
    根据具体需求选择合适的缓存方式,可以提高应用的性能和用户体验。
由 Hexo 驱动 & 主题 Keep
访客数 访问量