chrome插件之存储系统

4,197 阅读5分钟

一、前言

chrome插件之所以如此受欢迎,是因为它为开发者提供了完备的API,本篇文章就来介绍一下chrome插件的存储系统,也就是说chrome为我们提供了类似我们在web环境下使用localStoragesessionStorage的API。

这个API位于chrome环境下的chrome.storage,以下我们将chrome插件提供的存储能力统称为StorageAPI。

二、概览

1.是什么?

StorageAPI为我们提供了在chrome插件环境下持久化存储数据和状态的能力,就像web端的API IndexedDB, 和 Storage一样,但是相比他们,StorageAPI更加符合chrome插件的需要,并且具备以下特性:

  • 所有的chrome插件环境中都可以访问StroageAPI,因此可以很方便的管理全局的状态。
  • 使用webStorage时,我们需要将想要存储的对象序列化,否则无法实现我们希望的存储,但是StorageAPI可以直接存储一个对象,便于开发者维护和管理。
  • StorageAPI是异步的,采用批量读写的操作。
  • 即使用户清除浏览器缓存或历史,StorageAPI依然为我们持久化存储数据状态。

2.为什么需要?

qs:为什么不直接使用webStorage?

众所周知,我们在chrome插件中也可以使用webStorage,例如在content.js 、pupop.html、chrome.tabs.create({url:"path"}) 创建的新tab等中都可以使用webStorage。那为什么还需要StorageAPI呢?主要是由于以下原因:

  • background.js脚本无法访问webStorage,因为它只是一个脚本运行环境,不承载任何UI界面。
  • content.js和宿主站点是共享webStorage的,宿主环境的脚本也有可能修改webStorage的状态。
  • 当我们清除浏览器缓存后,webStorage就一并消失了。

基于以上的原因,chrome插件希望为自己提供一套统一的、干净的、更强大的全局存储状态的工具,才有了StorageAPId的出现。

3.有哪些类型?

StorageAPI有四个不同的区域来实现不同特性的存储功能:

storage.local

这个区域属于本地存储,只有当插件被移除卸载后数据才会被清除,所以你关闭浏览器或者清除浏览器缓存都无法将所存储的状态清除。

它的存储大小限制在10MB以内,当然如果在manifest.jsonpermission配置中添加"unlimitedStorage"配置的话,它的存储限制会进一步被提高。

温馨提示:
在chrome114之前的版本,它的默认限制是5MB。

storage.sync

Snipaste_2023-08-17_16-38-03.png

在chrome设置中,我们可以选择开启同步模式,它的好处就是对于同一个用户而言,所有登录谷歌账号的终端设备都可以共享部分数据。换句话说,如果我拥有一个谷歌账号,我在不同主机上的浏览器可以共享一些数据。

而sync就支持这样的功能,通过storage.sync可以获取同一用户的不同终端的全量的数据和状态。当然如果没有开启同步模式的时候,它的表现就和storage.local是一样的。

当浏览器离线时,Chrome将数据存储在本地,并在重新上线时恢复同步,它的存储限制大约为100 KB。我们可以考虑使用它来保存跨同步浏览器的用户设置。

storage.local和storage.sync不应该存储机密用户数据,因为它们没有加密。在处理敏感数据时,考虑使用会话存储区域在内存中保存值,直到浏览器关闭。

storage.session

如果说storage.local和storage.sync是存储在磁盘上的话,storage.session在浏览器会话期间将数据保存在内存中。默认情况下,它不会暴露给内容脚本,但是可以通过设置chrome.storage.session.setAccessLevel()来改变这种行为,存储限制大约是10BM。考虑使用它来存储跨service worker运行的全局变量。

storage.manage

该存储区域是只读的,一般不会用到它,需要声明一个schema.json才可以使用该API。

4.条件

要真正的在chorme插件环境中使用,需要我们在manifest.json中显示的声明permission:

{
  "name": "My extension",
  ...
  "permissions": [
    "storage"
  ],
  ...
}

三、使用

他们的使用方法如下:


// local
chrome.storage.local.set({ key: value }).then(() => {
  console.log("Value is set");
});

chrome.storage.local.get(["key"]).then((result) => {
  console.log("Value currently is " + result.key);
});

//sync
chrome.storage.sync.set({ key: value }).then(() => {
  console.log("Value is set");
});

chrome.storage.sync.get(["key"]).then((result) => {
  console.log("Value currently is " + result.key);
});

//session
chrome.storage.session.set({ key: value }).then(() => {
  console.log("Value was set");
});

chrome.storage.session.get(["key"]).then((result) => {
  console.log("Value currently is " + result.key);
});

案例

接下来准备一个案例来具体的说明local和session的使用

第一步:创建一个chrome插件项目

结尾有git仓库代码,可以直接down下来测试

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>popup</h1>
    <select name="type" id="storage-type">
      <option value="local">local</option>
      <option value="session">session</option>
    </select>
    <input type="text" id="storage-value" />
    <button id="storage-btn">存储</button>
    <br />
    <button id="storage-show">数据</button>
    <div id="storage-view"></div>
    <script src="./popup.js"></script>
  </body>
</html>

// popup.js
document.getElementById("storage-btn").addEventListener("click", () => {
  const value = document.getElementById("storage-value").value;
  const type = document.getElementById("storage-type").value;

  if (type === "session") {
    chrome.storage.session.set({ session: value }).then(() => {
      console.log("设置local值成功");
    });
  } else {
    chrome.storage.local.set({ local: value }).then(() => {
      console.log("设置session值成功");
    });
  }
});

document.getElementById("storage-show").addEventListener("click", () => {
  chrome.storage.local.get(["local"]).then(({ local }) => {
    chrome.storage.session.get(["session"]).then(({ session }) => {
      document.getElementById("storage-view").innerHTML = `
        <span>local value</span>: ${local} \n
        <span>session value</span>: ${session}
      `;
    });
  });
});

以下是演示视频:

屏幕录制2023-08-17 下午6.44.17.gif

接下来我将浏览器关闭,然后我们看看数据状况如何:

屏幕录制2023-08-17 下午6.46.58.gif

可以看到session的状态已经丢失了,但是local的状态依然存在。

onChanged

有的时候我们希望监听全局状态的变化,我们可以使用StorageAPI提供的onChanged方法。

在上面的案例中我们增加一个background.js,在后台监听。

chrome.storage.onChanged.addListener((changes, namespace) => {
  for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
    console.log(
      ` "${namespace}" 区域 有一个属性"${key}" 发生了变化`,
      `旧值为 "${oldValue}",新值为"${newValue}".`
    );
  }
});

image.png

我们可以看到不同区域的任何一个状态发生变化都可以察觉到,然后在这个函数中我们可以写不同的处理逻辑就好了。

好啦,以上就是本篇chrome插件存储系统的所有知识了,大家可以自己也尝试一下!

四、资源

以上的案例位于 chrome-extensions-learn.git仓库

五、最后的话

以下是我的其他文章,欢迎阅读

保姆级讲解JS精度丢失问题(图文结合)

shell、bash、zsh、powershell、gitbash、cmd这些到底都是啥?

从0到1开发一个浏览器插件(通俗易懂)

用零碎时间个人建站(200+赞)

另外我有一个自己的网站,欢迎来看看 new-story.cn

创作不易,如果您觉得文章有任何帮助到您的地方,或者触碰到了自己的知识盲区,请帮我点赞收藏一下,或者关注我,我会产出更多高质量文章,最后感谢您的阅读,祝愿大家越来越好。