JavaScript caching framework for client side caching in the browser
github.com
github.com
So if you're in a random internet café checking your email on a site that uses this library to cache your emails and then close the browser and leave all that private information, your email content, is cached on that browser. If a savvy enough person saw you on this site and knew what it did that individual could go to the browser and simply use Web Inspector, in the case of Chrome, and check out what was cached and read all of your cached emails.
There is no way for the client to know it's not a secure environment unless you ask the user. You also could delete the cache on log out, but what you can't do is delete the cache when the browser or tab closes, because then you don't have a cache at all. And more than likely most devs wont even think on this and just imagine that their cache will expire at some point.
Gmail solves this problem by requiring a per browser opt-in via, on Chrome at least, a browser extension for client side caching.
I haven't investigated to see if there's some way to use the HTML5 cache.appcache window.applicationCache to solve this problem. That actually has an expire.
Browsers have complex mechanisms in place to deal with broken firewalls, high-latency links, non-conformant servers and proxy. Any client-side caching implementation is going to be slower and less complete than its browser counterpart.
Another important issue is that all browsers already have caching mechanisms built in. Spend your time verifying and correcting that your headers are being set properly for your js and stylesheets.
Also, localStorage only gives you 5mb of storage. That space can be taken up very quickly if you aren't careful.
There are some very limited cases where this kind of thing can be useful. One that I'm reminded of is mobile web applications. Steve Souders talked about this briefly at the jQuery conference around this time last year. However, all the major mobile browsers already support cache manifests, which mostly obviates the need for something like this.
I originally created this handle working with an external API in a simple static files only app. It works really well for that usecase and solved my issues. It was then easy to make in a general way, so I decided to chuck it out in the wild and see if I can help anybody else.
Perhaps I should add an area to the README to define when you should (and maybe more importantly when you shouldn't) use this.
Another big thing that's missing is partial forced expiration. This is when the entire page is cached, but certain blocks are excluded from caching. Upon the next request to the same page, the browser sends a normal request with one addition: an extra header listing the transient blocks. Thus, the server has an opportunity to respond with updates only, rather than the entire page.
Moreover, SPDY is a highly complex proposition, whereas what I'm describing is dead-simple. I have implemented something very similar using JS, cookies and local storage. Of course a built-in browser support would be much, much more desirable.
With HTML5 Offline (App Cache) you could easily do this on the application level, of course. And with SPDY you can just fetch the fragments separately without any performance penalty. Basically current trend is to enable more gradual caching instead of implementing some higher level resource multiplexing.
Biggest missed opportunity in my opinion? Preparsed DOM/XML. E.g. Fast Infoset[1].
I thought a bit about your solution, and I guess it’s doable using existing technology AND leveraging gradual caching without JS.
Browsers would just have to support Xinclude[1].
For example:
> GET /foo
< 200 OK HTTP/1.1
< ETag: 1
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml
xmlns:xi="http://www.w3.org/2001/XInclude>
<head>...</head>
<body>
...
<p><xi:include href="fragment" parse="text"/></p>
</body>
</html>
Using standard HTTP/1.1 session protocol this would require additionally requesting /foo/fragment, SPDY can just use SS push. > GET /foo/fragment
< 200 OK HTTP/1.1
< Etag: 1
[…]
Now on refresh conditional GET for /foo hits cache, and conditional GET for /foo/fragment doesn’t. Abracadabra: partial caching. > GET /foo
> If-None-Match: 1
< 304 Not Modified HTTP/1.1
> GET /foo/fragment
> If-None-Match: 1
< 200 OK HTTP/1.1
< Etag: 2
[…]
While it looks like some new technology, it’s simple really. Browsers already compose pages by fetching scripts, images, embedded objects, iframes. This is not that different.Moreover, this approach provides backwards compatibility, because if the browser doesn’t resolve XInclude, you can just do that yourself using AJAX.
This solves your problem, but requires changes only on the client side.
Perhaps worth using under the hood for locache?
http://amplifyjs.com/api/store/
I have nothing to do with that project but I hate to see people re-invent the wheel. ;-)
1. why have a different method for multiple values rather then check parameter type for the normal methods (e.g. if 'set' received an object or get received an array).
2. getMany returns an array instead of an object mapping key to value. Sure may be more efficient but less convenient to use.
Pull requests, issues etc. all welcome. Otherwise, I'll have a look at it myself.