从输入浏览器到页面展示涉及的缓存机制
从用户在浏览器地址栏输入 URL 到页面最终展示,整个过程中涉及多层缓存机制,这些缓存共同作用,提高网页加载速度和用户体验。以下是详细介绍:
1. DNS 缓存
当输入 URL 后,首先需要进行 DNS 解析,将域名转换为 IP 地址,这个过程涉及以下缓存:
- 浏览器 DNS 缓存:浏览器会缓存之前查询过的域名解析结果 
- 操作系统 DNS 缓存:如果浏览器缓存中没有,会查询操作系统的 DNS 缓存 
- 路由器 DNS 缓存:家庭或公司网络的路由器也会缓存 DNS 记录 
- ISP 的 DNS 服务器缓存:互联网服务提供商的 DNS 服务器维护的缓存 
// 查看Chrome浏览器的DNS缓存(在开发者工具中执行)
chrome.net.dns.getResolveInfo("example.com", (result) => {
  console.log(result);
});2. TCP 连接缓存
建立 TCP 连接时也有缓存机制:
- TCP 连接复用:HTTP/1.1 的 Keep-Alive 和 HTTP/2 的多路复用允许在同一 TCP 连接上发送多个请求 
- TCP Fast Open:允许在握手过程中发送数据,减少往返时间 
3. 网络请求缓存
3.1 浏览器 HTTP 缓存
- 强缓存:通过 - Cache-Control和- Expires头控制
- 协商缓存:通过 - ETag和- Last-Modified头实现
// 服务器返回的响应头示例
Cache-Control: max-age=3600
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT3.2 Service Worker 缓存
Service Worker 作为 Web 应用程序与浏览器之间的代理服务器,可以拦截网络请求并缓存资源:
// Service Worker注册
navigator.serviceWorker.register("/sw.js");
// 在sw.js中缓存资源
self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open("v1").then((cache) => {
      return cache.addAll([
        "/",
        "/styles/main.css",
        "/scripts/main.js",
        "/images/logo.png",
      ]);
    })
  );
});
// 拦截请求并从缓存中响应
self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});3.3 CDN 缓存
内容分发网络在全球各地的节点上缓存静态资源,减少请求延迟:
- 边缘节点缓存:离用户最近的 CDN 节点缓存内容 
- 区域节点缓存:CDN 的中间层缓存 
- 源站缓存:CDN 源站的缓存层 
4. 浏览器渲染过程中的缓存
4.1 资源缓存
- 内存缓存(Memory Cache):加载过的资源存储在内存中,页面关闭后失效 
- 硬盘缓存(Disk Cache):持久化存储的 HTTP 缓存,关闭浏览器后仍然有效 
4.2 渲染缓存
- 脚本编译缓存:V8 引擎会缓存编译后的 JavaScript 代码 
- 字体缓存:已下载的 Web 字体会被缓存 
- 图片缓存:解码后的图片数据会被缓存 
// 检查资源是否来自缓存
performance.getEntriesByType("resource").forEach((resource) => {
  if (resource.transferSize === 0) {
    console.log(`${resource.name} 来自缓存`);
  }
});4.3 DOM/CSSOM 缓存
- DOM 缓存:浏览器会缓存构建好的 DOM 树 
- CSSOM 缓存:样式计算结果会被缓存 
5. 应用层缓存
5.1 LocalStorage 和 SessionStorage
// 使用LocalStorage缓存数据
localStorage.setItem("user", JSON.stringify({ name: "张三", id: 123 }));
// 读取缓存数据
const user = JSON.parse(localStorage.getItem("user"));5.2 IndexedDB
// 打开IndexedDB数据库
const request = indexedDB.open("myDatabase", 1);
// 创建对象存储
request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore("users", { keyPath: "id" });
};
// 存储数据
request.onsuccess = (event) => {
  const db = event.target.result;
  const transaction = db.transaction(["users"], "readwrite");
  const store = transaction.objectStore("users");
  store.put({ id: 1, name: "李四", age: 35 });
};5.3 Web Storage API (Cache API)
// 打开缓存
caches.open("app-v1").then((cache) => {
  // 添加资源到缓存
  cache.add("/api/data.json");
  // 或者添加多个资源
  cache.addAll(["/styles/app.css", "/scripts/app.js"]);
});
// 从缓存获取资源
caches.match("/api/data.json").then((response) => {
  if (response) {
    return response.json();
  }
});6. 预加载缓存
浏览器的预加载机制也会影响缓存:
- DNS 预解析: - <link rel="dns-prefetch" href="//example.com">
- 预连接: - <link rel="preconnect" href="//example.com">
- 预获取: - <link rel="prefetch" href="/page-2.html">
- 预渲染: - <link rel="prerender" href="/page-likely-to-be-visited-next.html">
总结
这些缓存机制在不同层面协同工作,共同提高网页加载性能。在实际开发中,合理利用这些缓存机制,可以显著提升用户体验,减少服务器负载和带宽消耗。
最后更新于
这有帮助吗?