Sign up ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

The idea is to make use of HTML5 local storage to store frequently accessed CSS and JavaScript.

For example (pseudo-code):

var load_from_cdn = true;
if (detect local storage)  
  if (cache of css, js found)
     load the local storage cache
     load_from_cdn = false;
if (load_from_cdn)

Is this possible or realistic?

I do aware browser cache, there will be still some header access checking,
I assuming no HTTP access is better (in my thinking)

PS : It seems that local storage only support key-value pair, can someone prove it ?
(best with some examples)

share|improve this question
Wikipedia apparently tried this to great effect: – Dave Dec 4 '13 at 13:05
that's my 2 years ago idea ... :) – ajreal Dec 4 '13 at 14:33
Your question was the first thing I found when I googled about it. There was a lot of discussion here about whether it was a good idea or not, so I thought I'd provide some anecdotal evidence in favor! – Dave Dec 4 '13 at 14:50
That picture is misleading. If you scroll further down you can see that the huge drop was not in fact because localstorage was better than caching, but rather a bug in their caching setup: "Turned out to be less spectacular :( . Graph is of internal traffic, drop due to localStorage hiding caching bug" - – Jamie Barker Jul 7 at 11:24

7 Answers 7

up vote 10 down vote accepted

It is absolutely OK to use local storage to store JS and CSS. However, local storage has 5M per domain limitation. You might have to reconsider this strategy.

For desktop web, you can leverage default browser cache to do the trick. Just set the JS & CSS HTTP response to be cacheable. It is simple and easy.

For mobile web, latency is high. So, reducing HTTP requests is critical. So, having JS & CSS in external URL's is optimal. It would be much better to have JS & CSS inline. This reduce HTTP requests, but bloated the HTML content. Then What? Just as you said, use local storage!

When one browser visits the site for the first time, JS & CSS are put inline. The JS also has two more jobs: 1) Store JS & CSS into local storage; 2) Set cookie to flag that JS & CSS are in local storage.

When the browser access the site for the second time, server got the cookie and know that the browser already have related JS & CSS. So the render HTML has inline JS to read JS & CSS from local storage and insert into DOM tree.

This is basic idea how mobile version is created. You may need to put JS&CSS version control into consideration when implement it in production.


share|improve this answer
Yes, pretty close to what I thinking of. – ajreal Sep 23 '11 at 8:27
Google developed a module for Page Speed Mod that does the very same thing. Here's the page where they talk about the goods, bads and dontknows… – tacone Aug 1 at 0:59
upvoted, but wtf does "inline" mean in this case. "inline" has like 5 different meanings. – Alex Mills Sep 4 at 8:06

Doesn't the browser already do this for you, and probably better?

share|improve this answer
one would hope – Alex Mills Sep 4 at 8:07

What's the point?

There is already a well established technique called client-side caching. What does HTML5 local storage brings in this case what caching is missing?

You may have some sort of strange application which must load chunks of JavaScript code dynamically so you can't effectively use the cache, but it's an extremely rare case.

Also, be aware of another thing. Browsers have specific policies for cache, and most browsers are quite good at managing cache well (removing only the older content, etc.). By implementing your home-made cache, you prevent the browsers from managing it correctly. Not only it can be criticized on its own, but it will also hurt you soon or later. Example: when the users of a web application are reporting bugs, often you answer by asking them to clear their cache. I'm not sure what you'll ask in your case, since clearing the cache will never resolve issues with your web app.

In response to your first edit (your second edit being off-topic):

I do aware browser cache, there will be still some header access checking

You seem to lack some understanding of browser caching. That's why it is essential to understand how it works first, before starting to implement your own home-made caching mechanism. Reinvent your own wheel only when you understand enough the existent wheels and have a good reason to not use them. See point 1 of my answer to the question "Reinventing the wheel and NOT regretting it".

When providing some data through HTTP, you can specify a few headers related to the cache:

  • Last-Modified specifies when the content was changed,
  • Expires specifies when the browser must ask to the server if the content changed.

Those two headers allow the browser to:

  • Avoid downloading the content again and again. If Last-Modified is set to the last month, and the content was already downloaded today a few hours before, there is no need to download it again.
  • Avoid querying for the date where the file was last modified. If Expires of a cache entity is May 5th, 2014, you don't have to issue any GET request neither in 2011, nor in 2012 or 2013, since you know that the cache is up-to-date.

The second one is essential for CDNs. When Google serves JQuery to a visitor of Stack Overflow or serves images or stylesheets used by Stack Overflow, they do not want browsers to query for a new version every time. Instead, they are serving those files once, set the expiration date to something long enough, and that's all.

Here's for example a screenshot of what's happening when I come to Stack Overflow home page:

A screenshot of Stack Overflow timeline in Chrome shows 15 files, 3 being requested, 12 being served from cache directly with no requests to remote servers

There are 15 files to serve. But where are all those 304 Not Modified responses? You only have three requests of content that changed. For everything else, the browser uses the cached version without making any request to any server.

To conclude, you really need to think twice before implementing your own cache mechanism, and especially find a good scenario where this can be useful. As I said at the beginning of my answer, I can find only one: where you are serving chunks of JavaScript to use them through, OMG, eval(). But in this case, I'm pretty sure that there are better approaches which are either:

  • More effective using the standard cache techniques, or
  • Easier to maintain.
share|improve this answer
+1 for this one. It is absolutely pointless. Almost in all cases absolutely. Caching by some unique, hash-based key is way better. – shabunc Sep 16 '11 at 9:22
You are not entirely right about the browser cache. A hard refresh will by pass all the browser cache checking. – ajreal Sep 23 '11 at 8:23
The link to reinventing the wheel and not regretting it is dead :'( – Esailija Jan 28 '12 at 8:52
Bowser caching is not as straight forward as you may think, nor is it consistent across all browsers. For example, some browsers randomly decide to load web fonts (regardless of headers - can't find the article about this right now but I think it was Dave Rupert who discovered this). Also, ETAGs force browsers to check if a resource has been updated... and sometimes you can't remove ETAG (eg. Amazon S3) - so if your CSS file sends an ETAG header, it will always be checked for updates (304s are still a payload). In order to prevent unnecessary requests, custom caching is required. – Ryan Wheale Nov 26 '14 at 17:47

Client-side local caching should be way more optimized than using HTML5 local storage. Just make sure your javascript and CSS are in external cachable files and your page should load much quicker via browser cache than trying to extract them from local storage and execute them yourself.

Besides, the browser can start loading external resources as the page starts to load, before you can actually start running javascript in that page to then get your resources from HTML5 local storage.

Plus, you need code in the page anyway in order to load from HTML5 local storage, so just put all your JS in one external, cachable JS file.

share|improve this answer

Instead of reinventing the wheel just use the HTML5 offline functionality:

share|improve this answer

You'll get much better performance by using a content delivery network (CDN) like Google's code library. Planned thoughtfully, the majority of your JS and CSS should be in every visitor's cache before they hit your site for the first time. Minify the remainder.

You can always benchmark browser caching vs your hand-rolled HTML5 solution. But my bet is that the native caching is going to beat the pants off it.

share|improve this answer

Using localStorage is fast(er)! My test showed

  • Loading jQuery from CDN: Chrome 268ms, FireFox: 200ms
  • Loading jQuery from localStorage: Chrome 47ms, FireFox 14ms

I guess saving the HTTP request already brings a big speed advantage. Everybody here seems to be conviced of the opposite, so please prove me wrong.

If you want to test my results I crated a tiny library that caches scripts in localStorage. Check it out on Github or just copy it from the example below.

The complete library:

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))};"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)};

Calling the library

requireScript('jquery', '1.11.2', '', function(){
    requireScript('examplejs', '0.0.3', 'example.js');
share|improve this answer
Your measures are irrelevant. (1) If the user is new to the website, he has no jQuery in local storage anyway. (2) If, on the other hand, the user already visited your website, he has jQuery in cache, which means that it won't be loaded from CDN. This also leads to a third point: (3) local storage is proper to a given site, while jQuery on Google's CDN is shared by many sites, which means that a user who visited, say, Stack Overflow but is new to your site won't need to reload jQuery from CDN if you use the same version of jQuery. – MainMa Mar 8 at 16:23
@MainMa Maybe this measure is not good, I see that now, but for the browser cache to work there needs to be a request send to a server which then returns a 304. This request takes more time than directly getting the file form the localstorage. Correct me if I'm wrong. – select Sep 7 at 14:51
@MainMa please also check the comments from there are more issues with the cache, like the ETAG comparison that make this custom caching faster – select Sep 7 at 14:57

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.