浏览器存储
浏览器存储就是前端保存数据的仓库,可以用于保存用户状态、登录令牌、缓存数据、离线内容等。
🗂️ 浏览器常见存储方式对比
存储方式 | 容量限制 | 生命周期 | 可跨页 | 同源策略 | 使用场景 |
---|---|---|---|---|---|
Cookie | ~4KB | 可设置过期时间 | ✅ | ✅ | 认证(HttpOnly )、服务端读写 |
localStorage | ~5MB | 永久(手动清除) | ✅ | ✅ | 持久数据,用户偏好等 |
sessionStorage | ~5MB | 页面会话 | ❌ | ✅ | 短期数据、单标签页状态 |
IndexedDB | 100MB+ | 永久 | ✅ | ✅ | 离线缓存、大数据、结构化对象 |
Cache Storage | 100MB+ | 永久 | ✅ | ✅ | Service Worker 缓存响应 |
🧾 各存储方式简要说明
1. 🍪 Cookie
- 存储在浏览器中,但通常用于 与服务端通信(会自动随请求发送)
- 支持 HttpOnly、Secure、SameSite 等属性
- 容量非常小,最多 4KB
- 用于认证、会话跟踪最合适
缺点
h5之前,存储主要用cookies,缺点:
- 容量缺陷。大小限制4k。
- 性能缺陷。请求头上带着数据,导致流量增加。Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ,请求都会携带上完整的 Cookie,这样随着请求数的增多,其实会造成巨大的性能浪费的,因为请求携带了很多不必要的内容。
- 安全缺陷。由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获,然后进行一系列的篡改,在 Cookie 的有效期内重新发送给服务器,这是相当危险的。另外,在HttpOnly为 false 的情况下,Cookie 信息能直接通过 JS 脚本来读取。
- 操作缺陷。Cookie的原生api不友好,需要自行封装
参数
参数 | 说明 |
---|---|
key | cookie key |
value | cookie value |
expires | 过期时间。一旦过期浏览器自动删除cookie。删除:可以设置一个过去的时间;如果不设置过期时间,则cookie有效期是会话期间。 |
path | 路径。在指定路径的时候,凡是来自同一服务器,URL里有相同路径的所有WEB页面都可以共享cookies。 |
domain | 主机名,是指同一个域下的不同主机,例如:www.baidu.com和map.baidu.com就是两个不同的主机名。默认情况下,一个主机中创建的cookie在另一个主机下是不能被访问的,但可以通过domain参数来实现对其的控制:document.cookie = "name=value;domain=.baidu.com" 这样,所有*.baidu.com的主机都可以访问该cookie。 |
secure | 当 secure 属性设置为 true 时,cookie 只有在 https 协议下才能上传到服务器,而在 http 协议下是没法上传的,所以也不会被窃听。 |
httponly | 用于防止客户端脚本通过 document.cookie 属性访问 Cookie,有助于保护 Cookie 不被跨站脚本攻击窃取或篡改。但是,HTTPOnly 的应用仍存在局限性,一些浏览器可以阻止客户端脚本对 Cookie 的读操作,但允许写操作;此外大多数浏览器仍允许通过 XMLHTTP 对象读取 HTTP 响应中的 Set-Cookie 头。 |
2. 📦 localStorage
- 每个域名最多 5MB
- 永久有效,除非用户手动清除或脚本清除
- 同步 API,易用但不能跨域
js
window.localStorage.username = 'hehe' // 设置
window.localStorage.setItem('username', 'hehe') // 设置
window.localStorage.getItem('username') // 读取
window.localStorage.removeItem('username') // 删除
window.localStorage.key(1) // 读取索引为1的值
window.localStorage.clear()
3. 🕒 sessionStorage
- 作用于单个标签页/窗口的会话
- 标签页关闭即清除,不能跨标签页共享
- 与 localStorage 使用方式一致
js
window.sessionStorage.username = 'hehe' // 设置
window.sessionStorage.setItem('username', 'hehe') // 设置
window.sessionStorage.getItem('username') // 读取
window.sessionStorage.removeItem('username') // 删除
window.sessionStorage.key(1) // 读取索引为1的值
window.sessionStorage.clear()
4. 🗃️ IndexedDB
- 浏览器提供的结构化对象数据库(NoSQL)
- 异步 API,基于事务,适合存储大量数据
- 可离线缓存图片、视频、JSON、表格等
js
const db = indexedDB.open('myDB', 1);
// 使用对象仓库存储 key-value 数据
5. 🧰 Cache Storage(Service Worker 缓存)
- 用于缓存 fetch 的请求与响应对
- 主要服务于 PWA、离线网页、前端资源缓存
- 可通过 caches 接口操作
js
caches.open('v1').then(cache => {
cache.add('/style.css');
});
如何用 Cache Storage 实现离线页面?
要使用 Cache Storage 实现一个离线页面(offline fallback page),你通常需要结合 Service Worker 来拦截网络请求,并在用户断网时返回缓存的离页页面。
🎯 实现目标
当用户访问网站时,如果网络可用则正常加载,若断网则显示离线页面(offline.html)
🧱 实现步骤概览
- 创建 service-worker.js
- 在其中缓存静态资源(含离线页)
- 拦截请求,尝试网络请求,失败时回退到离线页
- 页面中注册该 Service Worker
🧪 示例项目结构
bash
/index.html
/offline.html
/service-worker.js
/app.js
/style.css
1️⃣ 编写 service-worker.js
js
const CACHE_NAME = 'offline-cache-v1';
const OFFLINE_URL = '/offline.html';
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache => {
return cache.addAll([
'/', // index.html
'/offline.html', // fallback page
'/style.css',
'/app.js'
]);
})
);
self.skipWaiting();
});
self.addEventListener('activate', event => {
event.waitUntil(clients.claim());
});
// 核心逻辑:拦截请求,尝试网络,失败则返回 offline 页面
self.addEventListener('fetch', event => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request).catch(() => {
return caches.match(OFFLINE_URL);
})
);
}
});
2️⃣ 页面中注册 Service Worker
在 index.html 或其他入口页中加入
html
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(() => console.log('SW registered'))
.catch(err => console.error('SW registration failed', err));
}
</script>
3️⃣ 创建离线页面(offline.html)
html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>离线了</title></head>
<body>
<h1>你现在处于离线状态</h1>
<p>请检查你的网络连接。</p>
</body>
</html>