从输入浏览器到页面展示涉及的缓存机制
从用户在浏览器地址栏输入 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 GMT
3.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">
总结
这些缓存机制在不同层面协同工作,共同提高网页加载性能。在实际开发中,合理利用这些缓存机制,可以显著提升用户体验,减少服务器负载和带宽消耗。
最后更新于
这有帮助吗?