caching JavaScript files

Which is the best method to make the browser use cached versions of js files (from the serverside)?

Answers:

Answer

or in the .htaccess file

AddOutputFilter DEFLATE css js
ExpiresActive On
ExpiresByType application/x-javascript A2592000
Answer

I just finished my weekend project cached-webpgr.js which uses the localStorage / web storage to cache JavaScript files. This approach is very fast. My small test showed

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

The code to achieve that is tiny, you can check it out at my Github project https://github.com/webpgr/cached-webpgr.js

Here is a full example how to use it.

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

Calling the library

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');
});
Answer

From PHP:

function OutputJs($Content) 
{   
    ob_start();
    echo $Content;
    $expires = DAY_IN_S; // 60 * 60 * 24 ... defined elsewhere
    header("Content-type: x-javascript");
    header('Content-Length: ' . ob_get_length());
    header('Cache-Control: max-age='.$expires.', must-revalidate');
    header('Pragma: public');
    header('Expires: '. gmdate('D, d M Y H:i:s', time()+$expires).'GMT');
    ob_end_flush();
    return; 
}   

works for me.

As a developer you'll probably quickly run into the situation that you don't want files cached, in which case see Help with aggressive JavaScript caching

Answer

In your Apache .htaccess file:

#Create filter to match files you want to cache 
<Files *.js>
Header add "Cache-Control" "max-age=604800"
</Files>

I wrote about it here also:

http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/

Answer

The best (and only) method is to set correct HTTP headers, specifically these ones: "Expires", "Last-Modified", and "Cache-Control". How to do it depends on the server software you use.

In Improving performance… look for "Optimization on server side" for general considerations and relevant links and for "Client-side cache" for the Apache-specific advice.

If you are a fan of nginx (or nginx in plain English) like I am, you can easily configure it too:

location /images {
  ...
  expires 4h;
}

In the example above any file from /images/ will be cached on the client for 4 hours.

Now when you know right words to look for (HTTP headers "Expires", "Last-Modified", and "Cache-Control"), just peruse the documentation of the web server you use.

Answer

I have a simple system that is pure JavaScript. It checks for changes in a simple text file that is never cached. When you upload a new version this file is changed. Just put the following JS at the top of the page.

        (function(url, storageName) {
            var fromStorage = localStorage.getItem(storageName);
            var fullUrl = url + "?rand=" + (Math.floor(Math.random() * 100000000));
            getUrl(function(fromUrl) {
//                   first load
                if (!fromStorage) {
                    localStorage.setItem(storageName, fromUrl);
                    return;
                }
//                    old file
                if (fromStorage === fromUrl) {
                    return;
                }
                // files updated
                localStorage.setItem(storageName, fromUrl);
                location.reload(true);
            });
            function getUrl(fn) {
                var xmlhttp = new XMLHttpRequest();
                xmlhttp.open("GET", fullUrl, true);
                xmlhttp.send();
                xmlhttp.onreadystatechange = function() {
                    if (xmlhttp.readyState === XMLHttpRequest.DONE) {
                        if (xmlhttp.status === 200 || xmlhttp.status === 2) {
                            fn(xmlhttp.responseText);
                        }
                        else if (xmlhttp.status === 400) {
                            throw 'unable to load file for cache check ' +  url;
                        }
                        else {
                           throw 'unable to load file for cache check ' +  url;
                        }
                    }
                };
            }
            ;
        })("version.txt", "version");

just replace the "version.txt" with your file that is always run and "version" with the name you want to use for your local storage.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.