cross-storage 浏览器 Web 跨域本地缓存

发布于 2020-07-30 20:34:44 字数 6480 浏览 2917 评论 0

cross-storage 浏览器 Web 跨域本地缓存。允许跨不同域的多个浏览器窗口/选项卡共享单个本地存储。使用 ES6 Promise 提供一个 API。

该库是共享根域 cookie 的一种方便的替代方法。与cookie不同的是,客户端的数据不限于几千字节--最高可达249万个字符。对于客户端很重的应用程序,您可以通过避免cookie来减少几KB的请求头。这都要感谢 LocalStorage,它可以在 IE8+、FF 3.5+、Chrome 4+以及大多数移动浏览器中使用。

它怎么工作?库分为两种类型的组件:Hub 和 Client。Hub 驻留在选择的主机上,并直接与LocalStorageAPI交互。然后,客户端通过嵌入的 iframe 和 POST 消息加载所述 Hub,请求存储、检索和删除数据。这允许多个 Client 访问和共享位于单个存储区中的数据。

应注意限制双向交流的起源。因此,在初始化 Hub 时,传递一个权限对象数组。来自起源与模式不匹配的客户端的任何消息都将被忽略,以及那些不在允许的方法集合中的消息。由于相同的来源策略,权限集被强制执行。但是,请记住,任何用户都可以完全控制本地存储数据,仍然是客户端数据。这只会限制每个域或web应用程序级别上的访问。

Hub

// Config s.t. subdomains can get, but only the root domain can set and del
CrossStorageHub.init([
  {origin: /\.example.com$/,            allow: ['get']},
  {origin: /:\/\/(www\.)?example.com$/, allow: ['get', 'set', 'del']}
]);

注意用于匹配字符串末尾的 $。上面示例中的 RegExps 将匹配像 valid.example.com这样的起源,但不匹配 void.example.com.malicious.com。

Client

var storage = new CrossStorageClient('https://store.example.com/hub.html');

storage.onConnect().then(function() {
  return storage.set('newKey', 'foobar');
}).then(function() {
  return storage.get('existingKey', 'newKey');
}).then(function(res) {
  console.log(res.length); // 2
}).catch(function(err) {
  // Handle error
});

安装

可以通过 bower 安装:

bower install cross-storage

或者是使用 npm 安装:

npm install cross-storage

也可以使用 browserify:

var CrossStorageClient = require('cross-storage').CrossStorageClient;
var CrossStorageHub    = require('cross-storage').CrossStorageHub;

在为 Hub 服务时,您可能希望根据 客户机/Hub 位置设置服务器的 CORS 和 CSP 头。例如:

{
  'Access-Control-Allow-Origin':  '*',
  'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
  'Access-Control-Allow-Headers': 'X-Requested-With',
  'Content-Security-Policy':      "default-src 'unsafe-inline' *",
  'X-Content-Security-Policy':    "default-src 'unsafe-inline' *",
  'X-WebKit-CSP':                 "default-src 'unsafe-inline' *",
}

如果使用内联 JS 创建 Hub,则需要指定 unsafe-inline 对于 CSP 头。否则,如果简单地通过另一个资源包含 init 代码,则可以忽略它。

API

CrossStorageHub.init(permissions)

接受一个具有两个键的对象数组:origin 和 allow。源的值应该是一个 RegExp,并允许一个字符串数组。然后初始化跨存储中心以接受来自任何匹配源的请求,从而允许访问相关的方法列表。方法可以包括任意一个:get、set、del、getKeys 和 CLEAR。一旦完成,将向父窗口发送“ready”消息。

CrossStorageHub.init([
  {origin: /localhost:3000$/, allow: ['get', 'set', 'del', 'getKeys', 'clear']}
]);

new CrossStorageClient(url, [opts])

构造一个新的跨存储客户端,将 url 提供给 Hub。默认情况下,在指向 url 的文档正文中创建一个 iframe。它还接受 Options 对象,该对象可能包括超时值、框架ID 和 Promise。超时(以毫秒为单位)应用于每个请求,默认为 5000ms。Options 对象还可能包含一个 FraId,标识要在其上安装侦听器的现有框架。如果承诺键被提供给承诺的构造函数,则将使用该允诺库而不是默认的 window.promisel。

var storage = new CrossStorageClient('http://localhost:3000/hub.html');

var storage = new CrossStorageClient('http://localhost:3000/hub.html', {
  timeout: 5000,
  frameId: 'storageFrame'
});

CrossStorageClient.prototype.onConnect()

返回在与跨存储中心建立连接时履行的 Promise。它的使用是必要的,以避免在初始化完成之前发送任何请求。

storage.onConnect().then(function() {
  // ready!
});

CrossStorageClient.prototype.set(key, value)

设置指定值的键。返回在成功时实现的 Promise,或者如果发生设置键的任何错误或请求超时,则返回被拒绝的 Promise。

storage.onConnect().then(function() {
  return storage.set('key', JSON.stringify({foo: 'bar'}));
});

CrossStorageClient.prototype.get(key1, [key2], [...])

接受检索其值的一个或多个键。返回关于 Hub 响应或超时的 Promise 对象。在成功时,如果只传递一个参数,则使用键的值来实现。否则,它将使用一个值数组进行解析。在失败时,它将与相应的错误消息一起被拒绝。

storage.onConnect().then(function() {
  return storage.get('key1');
}).then(function(res) {
  return storage.get('key1', 'key2', 'key3');
}).then(function(res) {
  // ...
});

CrossStorageClient.prototype.del(key1, [key2], [...])

接受一个或多个键进行删除。返回关于集线器响应或超时的 Promise 对象。

storage.onConnect().then(function() {
  return storage.del('key1', 'key2');
});

CrossStorageClient.prototype.getKeys()

返回一个 Promise 对象,该 Promise 对象 在解析后传递当前存储中的一个键数组。

storage.onConnect().then(function() {
  return storage.getKeys();
}).then(function(keys) {
  // ['key1', 'key2', ...]
});

CrossStorageClient.prototype.clear()

返回一个 Promise,该 Promise 在解析后指示所有 localStorage 数据已被清除。

storage.onConnect().then(function() {
  return storage.clear();
});

CrossStorageClient.prototype.close()

删除iframe并将连接状态设置为false。客户端在被调用后不能再使用。

storage.onConnect().then(function() {
  return storage.set('key1', 'key2');
}).catch(function(err) {
  // Handle error
}).then(function() {
  storage.close();
});

兼容性

为了与较旧的浏览器兼容,只需加载一个 Promise polyfill 例如 es6-promise

您也可以使用RSVP或任何其他符合ES6的承诺库。支持IE8及以上使用上述填充。兼容视图中的IE8也需要一个JSON填充。还请注意catch是IE8中的一个保留字,因此使用承诺来处理错误可以这样做:

storage.onConnect().then(function() {
  return storage.get('key1');
}).then(function(res) {
  // ... on success
})['catch'](function(err) {
  // ... on error
});

关于 Safari 7+ (OSX, iOS)

默认情况下,Safari 7+ 所有跨域本地存储访问都将禁用。这是 阻止cookie和其他网站数据 隐私设置被设置为 来自第三方和广告商 的结果。任何跨存储客户端代码都不会崩溃,但是,它只能访问沙箱,孤立的本地存储实例。因此,以前由其他来源设定的数据都无法获取。如果是一个选项,您可以回到为这些用户代理使用根 cookie,或者从服务器端存储请求数据。

压缩

大多数与本地存储兼容的浏览器提供至少5MB的存储。但是键和值被定义为DOMStrings,它是使用单个16位序列编码的UTF-8.这意味着250万个ASCII字符的字符串将使用5MB,因为它们是每个字符2个字节。

如果需要最大化存储空间,请考虑使用 lz-string。对于较小的字符串,压缩时会看到大小减少50%,这将给您带来更接近500万字符的效果。此时,您只受到字符串的平均压缩速率的限制。

相关链接

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84935 人气
更多

推荐作者

淹不死的鱼

文章 0 评论 0

zhangMack

文章 0 评论 0

爱的故事

文章 0 评论 0

linces

文章 0 评论 0

早乙女

文章 0 评论 0

鸵鸟症

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。