19 存储

涉及面试题:有几种方式可以实现存储功能,分别有什么优缺点?什么是 Service Worker

cookie,localStorage,sessionStorage,indexDB

特性cookielocalStoragesessionStorageindexDB
数据生命周期一般由服务器生成,可以设置过期时间除非被清理,否则一直存在页面关闭就清理除非被清理,否则一直存在
数据存储大小4KB5M5M无限
与服务端通信每次都会携带在 header 中,对于请求性能影响不参与不参与不参与

从上表可以看到,cookie 已经不建议用于存储。如果没有大量数据存储需求的话,可以使用 localStoragesessionStorage 。对于不怎么改变的数据尽量使用 localStorage 存储,否则可以用 sessionStorage存储

对于 cookie 来说,我们还需要注意安全性。

属性作用
value如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识
http-only不能通过 JS 访问 Cookie,减少 XSS 攻击
secure只能在协议为 HTTPS 的请求中携带
same-site规定浏览器不能在跨域请求中携带 Cookie,减少 CSRF 攻击

Service Worker

  • Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全
  • Service Worker 实现缓存功能一般分为三个步骤:首先需要先注册 Service Worker,然后监听到 install 事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。以下是这个步骤的实现:
    // index.js
    if (navigator.serviceWorker) {
      navigator.serviceWorker
        .register('sw.js')
        .then(function(registration) {
          console.log('service worker 注册成功')
        })
        .catch(function(err) {
          console.log('service worker 注册失败')
        })
    }
    // sw.js
    // 监听 `install` 事件,回调中缓存所需文件
    self.addEventListener('install', e => {
      e.waitUntil(
        caches.open('my-cache').then(function(cache) {
          return cache.addAll(['./index.html', './index.js'])
        })
      )
    })
    
    // 拦截所有请求事件
    // 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据
    self.addEventListener('fetch', e => {
      e.respondWith(
        caches.match(e.request).then(function(response) {
          if (response) {
            return response
          }
          console.log('fetch source')
        })
      )
    })

打开页面,可以在开发者工具中的 Application 看到 Service Worker 已经启动了

Cache 中也可以发现我们所需的文件已被缓存

当我们重新刷新页面可以发现我们缓存的数据是从 Service Worker 中读取的

补充(现代做法):表中 indexDB 规范名应为 IndexedDB,容量并非真正“无限”,而是受浏览器配额(通常为磁盘可用空间的一定比例)限制。Service Worker 缓存现多用更高层的 Cache Storage API 配合 Workbox 管理;离线/PWA 场景优先用 Cache API + IndexedDB,而不是手动拦截 fetch。另外 SameSite 在现代浏览器默认值已为 Lax,跨站 Cookie 需显式设置 SameSite=None; Secure

Last Updated:
Contributors: leeguooooo