【翻译】本地存储并不简单
以下是翻译正文,水平有限难免会有错误,欢迎指正批评,多谢。
作者: Chris Heilmann
源文: There is no simple solution for local storage
必须要说,我们应该停止去推崇使用 localstorage
作为本地数据存储这个主张了,因为它在性能上的表现不并好。可悲的是,其他的替代品还无法很好的支持,或者是不易于使用。
在你做互联网开发的时候,你可能会遇到一些很优秀的东西。有时候它们看起来很棒,而阻止我们去使用的原因仅仅是作为程序员的“那些”观念(原文:Sometimes they are good, and all that stops us from using them is our notion of being conspicuous about everything as developers. )。然而更多的时候,在使用上一段时间以后,我们会发现其实它们也并不是真的那么优秀,好像我们选择错了。
对于上述提及的情况,其中一个例子就是本地存储。这篇关于存储的规范( storage specification,falsely attributed to HTML5 in a lot of examples)描述了其简洁和易用的API设计,它作为Cookie杀手一般横空出世。你只要通过 navigator.localStorage
接口即可在用户机器上存储内容(如果你只希望在用户当前浏览器会话过程中存储数据的话,也可以使用 sessionStorage
。)
localStorage.setItem('outofsight','my data'); console.log( localStorage.getItem('outofsight'));// ->'my data'
这个本地存储方案对web开发者来说有一些非常吸引人的特性:
- 真的非常简单。
- 存储字符串数据,不像数据库那样复杂(另外,你也可以通过JSON化编码来存储一些具有复杂格式的数据)
- 浏览器支持良好。
- 得到很多公司的认可和支持(原文:It is endorsed by a lot of companies (and was heralded as amazing when iPhones came out))。
但也存在少数的缺陷,如 无法明确的检测是否超过存储限制以及不同浏览器中存储容量有差异(原文:there is no cross-browser way to ask for more space)等。当然还有关于session和HTTPS的一些 模糊问题,不过这些都只是冰山一角,并无大碍。
最大的问题在于:糟糕的性能
localStorage也有很多没有被记录下来的缺点。尤其是性能优先的开发者因此反对使用。(原文:LocalStorage also has a lot of drawbacks that aren’t quite documented and certainly not covered as much in “HTML5 tutorials”. Especially performance oriented developers are very much against its use.)
当我们 使用localStorage来存储图片和文件信息时,于此( localStorage
)相关的问题便陆续暴露出来。主要的几个问题记录如下:
-
localStorage
本质上是同步的,这意味着,当它加载数据时会阻止文档的渲染。 -
localStorage
执行文件I/O操作,意味着它写数据到你的硬盘时,依赖于你的系统能力(索引、病毒扫描…)可能会花费较长的时间。 - 在开发者机器上这些问题可能被看作只是被系统缓存的请求,但对于web的最终用户来说意味着可能存在几秒的等待。
- 为了让响应更快,浏览器会在第一次加载的时候载入数据到内存中,这意味着如果大量的标签页面都是这样做的话,会占用大量的内存。
-
localStorage
是永久存储的。如果你不使用或者不再访问对应站点,这些数据始终会在浏览器启动时加载。
在Mozilla的性能小组成员 Taras Glek和来自Nokia的 Andrea Giammarchi的博文中有更详细的说明。
总的来说,你所看到的大量使用 localStorage
来提高性能的文章,是有问题的。
可选的替代方案
当然,浏览器总是需要提供一种存储本地数据的方式,一些你可能从未听说过的方案,比如 evercookie
(I think my fave when it comes to the “evil genius with no real-world use” factor is the force-cached PNG image to be read out in canvas)。在我们内部讨论后采用用 IndexedDB来替代localStorage方案。这篇文章说明了 如何使用IndexedDB来存储图片和文件信息,也因此发现了一些问题——主要还是易用性以及用户体验方面:
- IndexedDB是一个完整的数据库产品,读写数据与其他的SQL数据库一样需要指定的那些操作步骤,不像
localStorage
那样提供简单的key/value操作。 - IndexedDB会向用户申请数据存储的权限,这会让他们不知所措。
- 浏览器支持程度不如
localStorage
,目前只有 IE10、Firefox和Chrome支持IndexedDB,而且它们之间的实现也存在差异。 - Safari、Opera、iOS、Opera Mobile和Android的浏览器使用的是 WebSQL(这是 另外一个W3C的规范,不过已经被 废弃了)。
当实现存在兼容问题的时候,总会有人将它们进行抽象封装来解决这些问题。比如 Parashuram Narasimhan完成了这个伟大的兼容——甚至提供了jQuery插件。我们作为开发者,尽管感觉这不是好的方案,但还是得去使用它们,就像是当初 HTML5 Video关于 WebM vs. H264的辩论一样(原文:It feels wrong though that we as implementers have to use these. It is the HTML5 video debate of WebM vs. H264 all over again)。
现在该怎么办?
毫无疑问,真正的数据库的解决方案及其异步操作的特性在提高性能方面会是更好选择。同时它们也更加成熟,不会像 localStorage
有一种“简单粗暴(shortcut hack)”的感觉。另一方面,它们相对来说并不易于使用,况且我们已经有许多利用 localStorage
的解决方案在运行着,如果都要求用户给我们访问本地文件的权限的话,对于用户体验来说也是不可接受的。
所以说我们并没有一个真正简单简洁的方案在客户端上存储数据,我们应该停止去推崇使用 localStorage
来提升性能这种主张。我们需要找到一种让大家满意同时不会破坏目前的实现的解决方案。这也许很难做到,这里有一些想法:
- 建立一个 polyfill来替换现有的
localStorage
实现,利用IndexedDB/WebSQL来存储数据?这方案太糟了,而且也没有解决向用户申请权限的问题。 - 在浏览器中实现一个异步的
localStorage
——可能有效,但并没有对应的规范?(原文:Implement localStorage in an asynchronous fashion in browsers – actively disregarding the spec? (this could set a dangerous precedent though)) - 修改
localStorage
的规范,使用异步存储操作替代同步的数据存储?还可以扩展出getStorageSpace
接口,甚至原生支持JSON数据的存储。 - 定义一个新的标准,允许浏览器厂商定义新的API并映射到现有匹配的API接口?(原文:Define a new standard that allows browser vendors to map the new API to the existing supported API that matches the best for the use case?)
我们需要解决本地数据存储影响性能的问题(原文:We need to fix this as it doesn’t make sense to store things locally and sacrifice performance at the same time.)。这是一个典型的例子,新的互联网标准给我们带来更多的能力,与此同时也让我们面临更多之前没有遇到过的问题。我们对操作系统的访问权限越大,就越需要谨慎的对待这些问题。
========================= 正文分割线 ==========================
这篇来自 Chris Heilmann的《 There is no simple solution for local storage》发表以后,实际上在国外引起了相当的讨论——John Allsopp 的《 localStorage perhaps not so harmful》以及 Nicholas C.Zakas 的《 In defense of localStorage》,他们都在表达这样一个观点:localStorage引起的性能问题并没有那么大。年底的时候,Zakas又专门发表了《 Is localStorage performance a problem?》总结了这次的讨论。(国内似乎没有什么反响?)有兴趣的话,可以看看。
谈一下自己的感受。
当我看到这么一篇“唱反调”的文章时,还是比较惊讶的。一方面是我们从来不知晓这些存在的问题。另一方面,惊讶于他们的思考逻辑。
很多时候,我们关注的只是自己站点的性能效率,自己站点上的用户体验。我们宣称重视用户体验,其实很多时候都局限在自己的站点甚至自己负责的业务上。
对我来说,这算是观念上的一次刷新,也许我们应该站的离用户再近一点。