一、前言
chrome插件之所以如此受欢迎,是因为它为开发者提供了完备的API,本篇文章就来介绍一下chrome插件的存储系统,也就是说chrome为我们提供了类似我们在web环境下使用localStorage和sessionStorage的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.json的permission配置中添加"unlimitedStorage"配置的话,它的存储限制会进一步被提高。
温馨提示:
在chrome114之前的版本,它的默认限制是5MB。
storage.sync
在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}
`;
});
});
});
以下是演示视频:
接下来我将浏览器关闭,然后我们看看数据状况如何:
可以看到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}".`
);
}
});
我们可以看到不同区域的任何一个状态发生变化都可以察觉到,然后在这个函数中我们可以写不同的处理逻辑就好了。
好啦,以上就是本篇chrome插件存储系统的所有知识了,大家可以自己也尝试一下!
四、资源
以上的案例位于 chrome-extensions-learn.git仓库
五、最后的话
以下是我的其他文章,欢迎阅读
shell、bash、zsh、powershell、gitbash、cmd这些到底都是啥?
从0到1开发一个浏览器插件(通俗易懂)
用零碎时间个人建站(200+赞)
另外我有一个自己的网站,欢迎来看看 new-story.cn
创作不易,如果您觉得文章有任何帮助到您的地方,或者触碰到了自己的知识盲区,请帮我点赞收藏一下,或者关注我,我会产出更多高质量文章,最后感谢您的阅读,祝愿大家越来越好。