← 返回文章列表
浏览器与网络·382 次阅读

浏览器存储方案对比:Cookie、Web Storage 与 IndexedDB

浏览器存储方案对比:Cookie、Web Storage 与 IndexedDB

前端能用的存储就那么几种,但各自的设计目的完全不同。选型错误的代价很实际:我见过把几 MB 的用户数据塞 Cookie 的,每个请求都背着它来回跑,慢得莫名其妙。

Cookie:为请求而生的"小纸条"

Cookie 的本质不是存储,而是HTTP 协议的状态维持机制——服务器 Set-Cookie 之后,浏览器每次请求同域自动带上。这个特性决定了它的命运:

  • 容量极小,约 4KB,每个域名下数量有限
  • 每次请求自动携带,包括请求图片、CSS、接口——放多了全是带宽浪费
  • 有过期时间;HttpOnly 防 JS 读取,Secure 只在 HTTPS 下传输,SameSite 控制跨站携带

所以 Cookie 的正确用法只有一种:存服务器需要读的小数据,典型就是登录态标识(session id / token)。纯前端用的数据放 Cookie 里,是拿它的副作用当功能用。

Web Storage:纯前端的键值对

localStorage.setItem('theme', 'dark')
localStorage.getItem('theme')
localStorage.removeItem('theme')
  • 容量 5MB 左右(各浏览器不一),不参与请求,纯前端可用
  • localStorage 持久保存,除非主动清除;sessionStorage 只在当前标签页会话内有效,关页即清
  • API 是同步的,数据量大时会阻塞主线程
  • 只能存字符串,对象要 JSON.stringify / JSON.parse

sessionStorage 有个反直觉的点:新开标签页不会共享,但刷新页面会保留,而且通过链接新开的标签页会拷贝一份当时的快照,之后各自独立。想做"多标签页共享的临时状态"别指望它。

另外两个常见坑:

  1. 隐私模式/用户禁用 Cookie 时,写 localStorage 可能直接抛异常,关键逻辑要 try/catch
  2. localStorage 没有过期机制,自己存的业务数据要带时间戳字段,读的时候判断

IndexedDB:前端的小型数据库

当数据到了"几万条记录、需要按字段查询"的级别,就该 IndexedDB 出场了:

  • 容量大得多(一般是磁盘配额的一部分,几百 MB 起步)
  • 支持索引、事务、范围查询,是正经的数据库
  • 异步 API,不阻塞主线程
  • 可以存结构化对象、Blob、ArrayBuffer

代价是原生 API 非常难用(事件回调套娃),实战一律上封装库,比如 localForage(API 和 localStorage 一样简单)或者 Dexie(功能全)。

// localForage 的 API 和 localStorage 几乎一致,但是异步的
import localforage from 'localforage'

await localforage.setItem('draft', { title: '未发布', content: '...' })
const draft = await localforage.getItem('draft')

选型速查

需求 选择
登录态、服务端要读的标识 Cookie(HttpOnly)
主题、语言等小配置 localStorage
表单草稿、一次性向导状态 sessionStorage
大量结构化数据、离线应用 IndexedDB
敏感数据 都不存,或者加密后存,XSS 面前前端存储是透明的

别忘了还有 Cache Storage

PWA 场景下缓存接口响应和静态资源用的是 Cache Storage,和上面几个是不同体系,配合 Service Worker 使用。这个博客的主题切换、阅读偏好用的都是 localStorage,够用了。

总结成一句话:Cookie 是给服务器看的,Web Storage 是给 JS 看的小数据,IndexedDB 是给应用用的大数据。想清楚"谁要读这个数据",选型就不会错。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4