概述

2024年10月13日

  • Cookie是最古老和最基本的客户端存储机制之一。
  • Cookie是由服务器发送到用户浏览器的小型文本文件,存储在用户的计算机上。
  • Cookie是基于域的,不区分协议
  • 每次发送HTTP请求时,浏览器都会将相应的Cookie发送回服务器。
  • Cookie通常用于存储用户偏好设置、跟踪用户行为等信息。

限制

  • 格式: name=value, name和value都应该使用内建的 encodeURIComponent 函数对其进行转义
  • 大小: encodeURIComponent 编码后的 name=value 对,大小不能超过 4KB
  • 数量: 每个域的 cookie 总数在20到50左右,具体限制取决于浏览器。
  • 可以通过设置Cookie的过期时间来控制Cookie的生命周期。

安全性

  • path=/mypath:
    • 该路径下的页面可以访问该 cookie
    • 默认为当前路径
  • domain=site.com:
    • 控制可访问 cookie 的域
    • 默认(也就是不设置的话),不会共享给子域
    • 只有明确地将 domain 选项设置为根域,子域才能访问
      // 在 site.com
      // 使 cookie 可以被在任何子域 *.site.com 访问:
      document.cookie = "user=John; domain=site.com"
      
      // 之后
      // 在 forum.site.com
      alert(document.cookie); // 有 cookie user=John
      
  • expires, max-age
    • 如果没有设置这两个参数都没有设置,那么在关闭浏览器之后会消失,也就是session cookie
    • expires 要求使用 GMT 时区的这种格式
      // 当前时间 +1 天
      let date = new Date(Date.now() + 86400e3);
      date = date.toUTCString();
      document.cookie = "user=John; expires=" + date;
      
    • max-age: 单位为秒
  • secure
    • 表示该cookie只能通过HTTPS传输
  • samesite
    1. strict
    • 默认
    • 如果用户来自同一网站之外,那么设置了 samesite=strict 的 cookie 永远不会被发送
    1. lax
    • 和 strict 模式类似,当从外部来到网站,则禁止浏览器发送 cookie,除非满足两个条件
      1. HTTP 方法是“安全的”(例如 GET 方法,而不是 POST)。
      2. 该操作执行顶级导航(更改浏览器地址栏中的 URL)。
    • 缺点:会被到 2017 年左右的旧版本浏览器忽略(不兼容)
  • httpOnly
    • Web服务器使用 Set-Cookie header 来设置 cookie时,可以设置 httpOnly 选项
    • 禁止任何 JavaScript 访问 cookie

第三方cookie

  • 如果 cookie 是由用户所访问的页面的域以外的域放置的,则称其为第三方 cookie。
  • 通常用于跟踪和广告服务。它们被绑定在原始域上,因此第三方网站可以在不同网站之间跟踪同一用户,如果这些网站都可以访问该第三方网站的话

GDPR

  • 欧洲有一项名为 GDPR 的立法,该法规针对网站尊重用户实施了一系列规则。其中之一就是需要明确的许可才可以跟踪用户的 cookie。
  • 如果我们要设置带有身份验证会话(session)或跟踪 id 的 cookie,那么必须得到用户的允许。

参考


sessionStorage和localStorage

sessionStorage

  • sessionStorage是HTML5引入的Web存储机制之一,用于在浏览器中临时存储会话数据。
  • sessionStorage中存储的数据仅在当前会话期间有效,当用户关闭浏览器标签页或窗口时会被清除
  • sessionStorage中存储的数据仅限于当前页面或同源页面之间共享,不同页面之间的sessionStorage数据不会共享。

localStorage

  • localStorage也是HTML5引入的Web存储机制之一,用于在浏览器中持久存储数据。
  • localStorage中存储的数据在用户关闭浏览器后仍然保留,直到用户显式删除它们。
  • localStorage中存储的数据也只限于同源页面之间共享,不同源页面之间的localStorage数据不会共享。
  • 存满了会报错: QuotaExceededError

对比

  • 生命周期
    1. Cookie可以通过设置过期时间来控制生命周期
    2. sessionStorage的数据仅在当前会话期间有效
    3. localStorage的数据则在浏览器关闭后仍然保留。
  • 数据共享
    1. Cookie的数据则在同源或跨域请求中都会发送到服务器端。
    2. sessionStorage: 多窗口之间sessionStorage不可以共享状态,但是在某些特定场景下新开的页面会复制之前页面的sessionStorage
    3. localStorage的数据在同源页面之间共享
  • 存储容量
    • Cookie相对较小(几kb)
    • sessionStorage和localStorage通常具有更大的存储容量限制(几兆)

storage event

  • 不会冒泡

  • The storage event of the Window interface fires when a storage area (localStorage or sessionStorage) has been modified in the context of another document.

  • A way for other browsing contexts on the domain using the storage to sync any changes that are made.

  • Event properties

    1. key
    2. newValue
    3. oldValue
    4. storageArea
    5. url
  • 示例

    window.addEventListener("storage", () => {
      // When local storage changes, dump the list to
      // the console.
      console.log(JSON.parse(window.localStorage.getItem("sampleList")));
    });
    
  • Window: storage event - Web APIs | MDN

延伸

参考:


IndexedDB

概念

  • 浏览器中的数据库

用户能修改吗?

  • 答: Chrome浏览器并没有提供给用户直接修改的方式,但肯定能改。
  • 存储的位置位于(win11系统): c:\Users\USERNAME\AppData\Local\Google\Chrome\User Data\Default\IndexedDB\
  • 每个“源”有两个文件夹,类似于
    http_localhost_3001.indexeddb.blob
    http_localhost_3001.indexeddb.leveldb
    
    https_www.bilibili.com_0.indexeddb.blob
    https_www.bilibili.com_0.indexeddb.leveldb
    
    ps: 看到这就很好理解同源的要求了
  • 被加密了,但还是不推荐存储任何服务端敏感的内容于用户端
  • Edit IndexedDB data by using the Console tool - Microsoft Edge Developer documentation | Microsoft Learn

优化

虽然indexDB可以当数据库存很多图片(blob),但随着用户使用的时间变长,本地存放的图会越来越多,其实大部分是不会再用到的,数据一多,读取效率会打折扣,所以做了个FIFO存储队列,最多存50张。

参考


CacheStorage

  • This feature is available in Web Workers.

参考


浏览器缓存

定义

当我们访问一个网站时,会加载各种资源,如 HTML文档、JS、CSS、图片等。浏览器会将一些不经常变的资源保存在本地,这样下次访问相同网站时,就直接从本地加载资源,并不通过请求服务器,这就是浏览器缓存

分类

  • 根据位置分类

    • memory cache:主要用来缓存有 preloader 相关指令的资源;关闭tab页后就释放
    • disk cache
  • 根据是否需要和服务器进行通信分类

    • 强缓存
      • 不会向服务器发送请求,直接从缓存中读取资源
      • 通过ExpiresCache-Control来实现的
    • 协商缓存
      • 在强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识来决定是否使用缓存
      • 利用的是Last-Modified,If-Modified-SinceETag,If-None-Match这两对Header来管理

Response Header中的相关属性

  1. Expires
  • HTTP/1
  1. Last-Modified / If-Modified-Since
  • HTTP/1
  • 流程
    1. 浏览器第一次访问资源,服务器会 Response Header 里添加 Last-Modified 的值
    2. 浏览器在下一次请求这个资源的时候,检测到有Last-Modified这个 Header。浏览器就会在Request中加上 If-Modified-SinceIf-Modified-Since的值就是 Last-Modified 的值
    3. 服务器收到请求后,如果资源没有修改,服务器返回 304 Not Modified 状态码,并且不包含资源的内容。浏览器此时会使用本地缓存中的资源。
    4. 如果资源发生了修改,服务器会返回新的资源内容和更新后的 Last-Modified。
  1. Cache-Control
  • HTTP/1.1
  • 优先级比 Expires 要高
  • 可选值
    • public
    • private
    • no-store: 完全禁用缓存,资源不会存储在缓存中。
    • no-cache: 告诉浏览器要使用缓存文件,但是每次需要跟服务器确认是最新文件以后才能用,一般使用 Etag 或者 Last-Modified 字段来控制缓存
    • max-age=60
  1. ETag / If-None-Match
  • HTTP/1.1
  • ETag由服务器生成,三种方式:基于内容 / 基于版本 / 自定义生成
  • 浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match
  • ETag 的优先级要高于 Last-Modified
  • 解决了Last-Modified的如下问题
    1. 某些服务器不能精确得到文件的最后修改时间, 这样就无法通过最后修改时间来判断文件是否更新了。
    2. 某些文件的修改非常频繁,在秒以下的时间内进行修改. Last-Modified只能精确到秒。
    3. 一些文件的最后修改时间改变了,但是内容并未改变。 我们不希望客户端认为这个文件修改了。

如何禁用缓存(如何使缓存失效)

  • 场景一: 发版,要求无视缓存
    • 每次对应静态文件里有内容改动的时候,自动加一段 hash 到静态文件名里
  • 场景二: 用户自己想要刷新
    • F5 刷新: 因浏览器而异
    • Ctrl + F5 强制刷新的时候,会暂时禁用强缓存和协商缓存

后端配置

  • setHeader之类
  • Nginx 配置

参考


其他缓存

Memory Cache(内存缓存)

  • 特点:缓存存储在浏览器的内存中,主要用于存储从网络请求获取的资源(如 HTML、CSS、JavaScript 和图片)。这种缓存生命周期短,只在当前页面会话中有效,页面刷新或关闭后缓存会被清除。
  • 用途:用于快速重用同一页面内的资源,提升页面加载速度。
  • 存储时间:通常在页面刷新或关闭后即清除。
  • 优点:速度最快,适用于瞬时的页面资源重用。

Push Cache

  • 特点: 在用户并未明确请求某些资源的情况下,提前将这些资源推送到用户的缓存中。
  • 用途: 在用户即将需要某些资源时,提前发送这些资源,这样在用户实际请求时,可以直接从缓存中获取,而无需再次请求服务器。

Application Cache(AppCache)

  • 特点:这是 HTML5 中引入的离线缓存机制,允许开发者为 web 应用创建一个离线模式,用户即使断网也能访问缓存的内容。然而,由于 AppCache 有不少缺陷和安全隐患,已被弃用。
  • 用途:过去用于创建离线 web 应用,但目前已被 Service Worker 取代。
  • 状态:AppCache 从 HTML 5.1 开始废弃,现在大多数浏览器都不再支持。

WebSQL

  • 特点:WebSQL 是一种基于 SQL 的数据库,最初用于在浏览器中存储结构化数据。然而由于其标准化进程停止,WebSQL 不再是主流推荐的方案。
  • 用途:在浏览器中进行 SQL 查询和存储结构化数据,类似 IndexedDB 的早期版本。
  • 状态:已被 IndexedDB 取代。

Web Storage Cache API

  • 特点:缓存 API 是 Service Worker 的一部分,允许在浏览器中存储 RequestResponse 对象,常用于离线缓存。与普通缓存机制不同,开发者可以精确控制缓存的资源,并且缓存的内容可以在离线时访问。
  • 用途:用于离线支持、缓存管理、动态内容缓存,通常与 Service Worker 配合使用。
  • 优点:可控性更强,适用于现代 PWA(渐进式 Web 应用)的缓存策略。

Manifest Storage

  • 特点:一种较新的 API(如 Web App Manifest),允许开发者为应用程序提供缓存策略和应用图标等元数据,常用于渐进式 Web 应用(PWA)。
  • 用途:存储应用元数据,定义应用行为(如是否作为全屏应用、离线模式等)。

File System Access API

  • 特点:允许 Web 应用访问用户的文件系统,可以直接读写文件。通过这个 API,Web 应用可以处理用户计算机上的文件,实现类似桌面应用的体验。
  • 用途:用户可以在不离开浏览器的情况下,直接从文件系统中读取、修改和保存文件。
  • 状态:这是一个较新的 API,仍在部分浏览器中实现,安全性要求较高。

参考