使用HTML5本地存储来存储CSS和JavaScript是否现实


22

这个想法是利用HTML5本地存储来存储经常访问的CSS和JavaScript。

例如(伪代码):

var load_from_cdn = true;
如果(检测本地存储)  
{
  如果(找到CSS,JS的缓存)
  {
     加载本地存储缓存
     load_from_cdn = false;
  }
}
如果(load_from_cdn)
{
   document.write('<script> ...');
}

这是可能的还是现实的?

我知道浏览器缓存,但仍然会进行一些标头访问检查,
我认为没有HTTP访问会更好(我认为

PS:本地存储似乎仅支持键值对,有人可以证明吗?
(最好的例子)



1
那是我2年前的想法... :)
ajreal

您的问题是我在Google搜索时发现的第一件事。这里有很多关于它是否是一个好主意的讨论,所以我想我会提供一些轶事证据以示支持!
戴夫

1
那张照片令人误解。如果向下滚动,您会发现下降的幅度实际上并不是因为localstorage比缓存要好,而是它们的缓存设置中的一个错误:“事实证明,这种方法不太引人注目:(。图为内部流量,下降应归因于到localStorage隐藏缓存错误-twitter.com/catrope/status/408110382599782400
Jamie Barker

Answers:


11

使用本地存储来存储JS和CSS是绝对可以的。但是,本地存储每个域限制为5M。您可能必须重新考虑此策略。

对于桌面网络,您可以利用默认的浏览器缓存来完成此操作。只需将JS&CSS HTTP响应设置为可缓存。这很简单。

对于移动Web,延迟很高。因此,减少HTTP请求至关重要。因此,在外部URL中使用JS和CSS是最佳选择。内联JS&CSS会更好。这样可以减少HTTP请求,但会使HTML内容膨胀。那怎么了 就像您说的那样,请使用本地存储!

当一个浏览器首次访问该网站时,将JS和CSS内联。JS还有两个工作:1)将JS和CSS存储到本地存储中;2)设置cookie以标记JS和CSS在本地存储中。

当浏览器第二次访问该站点时,服务器获得了cookie,并且知道浏览器已经具有相关的JS和CSS。因此,渲染HTML具有内联JS,可以从本地存储读取JS和CSS并插入DOM树中。

这是bing.com移动版本创建的基本思路。在生产中实施JS&CSS版本控制时,您可能需要考虑它。

谢谢


是的,非常接近我的想法。
2011年

Google为Page Speed Mod开发了一个功能相同的模块。这里就是他们谈论的货物,劣品和dontknows页面developers.google.com/speed/pagespeed/module/...
tacone

赞成,但是wtf在这种情况下确实是“内联”的意思。“内联”有5种不同的含义。
亚历山大·米尔斯

1
实际上,桌面版已增加到10MB,移动版上增加了5MB
Roko C. Buljan

1
并不需要任何的cookie。你可以简单地看,如果localStorage的有你要找的键/值加上你必须提供一个版本(明显无效的目的)。此技巧只有在第二次访问该站点之后,并且如果资产不在缓存中(出于某种原因),这才是好选择
vsync


23

重点是什么?

已经有一种完善的技术,称为客户端缓存。在这种情况下,HTML5本地存储带来了什么?

您可能有某种奇怪的应用程序,该应用程序必须动态加载JavaScript代码块,因此您无法有效地使用缓存,但这是一种极为罕见的情况。

另外,请注意另一件事。浏览器具有特定的缓存策略,大多数浏览器都擅长很好地管理缓存(仅删除较旧的内容等)。通过实现自制的缓存,可以防止浏览器正确管理它。它不仅可以自己受到批评,而且还会早晚伤害您。示例:当Web应用程序的用户报告错误时,通常您会要求他们清除缓存来回答。我不确定您会问什么,因为清除缓存永远无法解决Web应用程序的问题。


响应您的第一次编辑(您的第二次编辑偏离主题):

我知道浏览器缓存,仍然会有一些标头访问检查

您似乎对浏览器缓存缺乏了解。因此,在开始实施自己的自制缓存机制之前,必须首先了解其工作原理。仅当您足够了解现有的车轮并且有充分的理由不使用它们时,才重新发明自己的车轮。请参阅我对“重新发明轮子而不后悔”问题的答案的第 1点。

通过HTTP提供一些数据时,您可以指定一些与缓存相关的标头:

  • Last-Modified 指定何时更改内容,
  • Expires指定何时浏览器必须询问服务器内容是否更改

这两个标头允许浏览器执行以下操作:

  • 避免一次又一次下载内容。如果Last-Modified设置为上个月,并且今天已经在几个小时前下载了内容,则无需再次下载。
  • 避免查询文件的最后修改日期。如果Expires缓存实体是2014年5月5 ,则您无需在2011年,2012年或2013年都发出任何GET请求,因为您知道缓存是最新的。

第二个对于CDN至关重要。当Google 向Stack Overflow的访问者提供JQuerycdn.sstatic.net为Stack Overflow 使用的图像或样式表提供服务时,他们不希望浏览器每次都查询新版本。相反,它们只提供一次这些文件,将到期日期设置为足够长的时间,仅此而已。

例如,这是当我进入Stack Overflow主页时发生的情况的屏幕截图:

Chrome中的Stack Overflow时间轴的屏幕快照显示了15个文件,其中3个正在请求中,其中12个是直接从缓存提供的,而没有对远程服务器的请求

有15个文件可供使用。但是这些304 Not Modified回应都在哪里?您只有三个内容更改的请求。对于其他所有内容,浏览器都使用缓存的版本,而不向任何服务器发出任何请求


总而言之,在实现自己的缓存机制之前,您确实需要三思而后行,尤其是找到一个有用的好方案。正如我在回答开始时所说的,我只能找到一个:OMG在其中提供JavaScript块以使用它们eval()。但是在这种情况下,我很确定有更好的方法是:

  • 使用标准缓存技术更有效,或者
  • 易于维护。

+1。这是绝对没有意义的。几乎在所有情况下都是绝对的。通过一些唯一的,基于哈希的密钥进行缓存会更好。
shabunc

1
您对浏览器缓存并不完全正确。硬刷新将通过所有浏览器缓存检查。
2011年

1
链接reinventing the wheel and not regretting it已死:'(
Esailija

4
Bowser缓存并不像您想像的那样简单明了,而且在所有浏览器中也不一致。例如,某些浏览器随机决定加载Web字体(无论标题如何,现在都找不到有关此的文章,但我认为是Dave Rupert才发现了此字体)。此外,ETAG会强制浏览器检查资源是否已更新...有时您无法删除ETAG(例如Amazon S3)-因此,如果您的CSS文件发送ETAG标头,则将始终检查它是否有更新(304s仍然是有效载荷)。为了防止不必要的请求,需要自定义缓存。
Ryan Wheale 2014年

7

客户端本地缓存应该比使用HTML5本地存储更优化。只需确保您的javascript和CSS位于外部可缓存文件中,并且您的页面应比通过尝试从本地存储中提取并自行执行更快地通过浏览器缓存加载。

此外,浏览器可以在页面开始加载时开始加载外部资源,然后才可以实际在该页面中运行javascript,然后从HTML5本地存储中获取资源。

另外,为了从HTML5本地存储中加载,您仍然需要页面中的代码,因此只需将所有JS放在一个外部可缓存的JS文件中即可。



2

通过使用诸如Google的代码库之类的内容交付网络(CDN),您将获得更好的性能。经过周密的计划,您的大多数JS和CSS应该在每个访问者首次访问您的网站之前都位于它们的缓存中。缩小其余部分。

您始终可以将浏览器缓存与手动滚动HTML5解决方案进行基准测试。但我敢打赌,本机缓存将使它脱颖而出。


2

使用localStorage更快(更)!我的测试表明

  • 从CDN加载jQuery:Chrome 268ms,FireFox:200ms
  • 从localStorage加载jQuery:Chrome 47ms,FireFox 14ms

我想保存HTTP请求已经带来了很大的速度优势。这里的每个人似乎都被判相反,因此请证明我错了。

如果要测试我的结果,我创建了一个微型库,该脚本在localStorage中缓存脚本。在Github上检查它https://github.com/webpgr/cached-webpgr.js或仅从下面的示例复制它。

完整的库:

function _cacheScript(c,d,e){var a=new XMLHttpRequest;a.onreadystatechange=function(){4==a.readyState&&(200==a.status?localStorage.setItem(c,JSON.stringify({content:a.responseText,version:d})):console.warn("error loading "+e))};a.open("GET",e,!0);a.send()}function _loadScript(c,d,e,a){var b=document.createElement("script");b.readyState?b.onreadystatechange=function(){if("loaded"==b.readyState||"complete"==b.readyState)b.onreadystatechange=null,_cacheScript(d,e,c),a&&a()}:b.onload=function(){_cacheScript(d,e,c);a&&a()};b.setAttribute("src",c);document.getElementsByTagName("head")[0].appendChild(b)}function _injectScript(c,d,e,a){var b=document.createElement("script");b.type="text/javascript";c=JSON.parse(c);var f=document.createTextNode(c.content);b.appendChild(f);document.getElementsByTagName("head")[0].appendChild(b);c.version!=e&&localStorage.removeItem(d);a&&a()}function requireScript(c,d,e,a){var b=localStorage.getItem(c);null==b?_loadScript(e,c,d,a):_injectScript(b,c,d,a)};

调用图书馆

requireScript('jquery', '1.11.2', 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function(){
    requireScript('examplejs', '0.0.3', 'example.js');
});

3
您的措施无关紧要。(1)如果用户是该网站的新手,则无论如何他在本地存储中都没有jQuery。(2)另一方面,如果用户已经访问过您的网站,则他在缓存中具有jQuery,这意味着它不会从CDN加载。这也引出了第三点:(3)本地存储适用于给定的站点,而Google CDN上的jQuery由许多站点共享,这意味着访问(例如,Stack Overflow但对您的站点是新的)用户获得胜利如果您使用相同版本的jQuery,则无需从CDN重新加载jQuery。
Arseni Mourzenko 2015年

@MainMa也许这种方法不好,我现在知道了,但是要使浏览器缓存正常工作,需要向服务器发送请求,然后服务器返回304。此请求比直接从localstorage获取文件要花费更多时间。 。如果我错了纠正我。
选择

也@MainMa请从注释programmers.stackexchange.com/a/105526/195684有更多的问题与缓存,像ETAG比较,让这个自定义缓存更快
选择
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.