ryandlf
ryandlf

Reputation: 28545

Stop Javascript and HTML from Loading From Cache

I am building a single page javascript app and when the application starts I use a single javascript file to load every other file I need on the fly. When I hit refresh, according to firebug, my HTML page as well as javascript pages will load with a 304 Not Modified Error and my javascript stops working.

I understand this is due to browser caching, but how can I avoid this? I load the initial HTML page with a single script call

<script src="js/config.js" type="text/javascript"></script>

and then continue to load the rest dynamically from within that script

window.onload = function () {
    var scripts = ['http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js', 'js/core.js', 'js/sandbox.js']; //Application scripts
    var loaded = 0;
    //Callback is executed after all scripts have been loaded.
    var callback = function () {
        if (loaded + 1 == scripts.length) {
            //Create Modules
            CORE.loader("js/modules/Login.js", function () {
                CORE.createModule('loginForm', Login);
            });

            //Create HTML bindings.
            CORE.createBinding('appContainer', '#Login', 'login.html');
            CORE.bindHTML(window.location.hash); //Loads hash based page on startup
        } else {
            loaded++;
            loadScript(scripts[loaded], callback);
        }
    };

    loadScript(scripts[0], callback);

    function loadScript(scriptSrc, callback) {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.src = scripts[loaded];

        if (script.readyState) {
            script.onreadystatechange = function () {
                if (script.readyState == 'loaded' || script.readyState == 'complete') {
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else {
            script.onload = function () {
                callback();
            };
        }

        document.getElementsByTagName('head')[0].appendChild(script);
    }
};

I know that Gmail uses cookies to prevent this. Does anyone have any idea how to take that approach? Should I set the cookie on the server and then check it with JS on each page load/refresh and use something like window.location.refresh() if the cookie tells me the page is loaded from cache?

Upvotes: 9

Views: 44187

Answers (8)

Nicolas Gu&#233;rinet
Nicolas Gu&#233;rinet

Reputation: 2216

I would suggest to use Javascript to generate a random number using Math.random multiply it and then Math.floor to return the integer of it. Then, I would add this number to the URL as a variable. Since the number changes during every page load, the file should never be cached.

<script id="myScript"></script>

<script>
  var url="yourscript.js?t=";
  var randomNum = String((Math.floor(Math.random() * 200000000000000)));
  document.getElementById('myScript').src = url+randomNum;
</script>

Upvotes: 1

Peter S McIntyre
Peter S McIntyre

Reputation: 413

<?php 
$xn = date("YmdHis");

echo  " <script	src='root.js?$xn'></script>";
?>

Upvotes: 1

Oranit Dar
Oranit Dar

Reputation: 1727

After struggling with the cache issue for months, trying just about anything (including a script which changes the URLs using a parameter) I found a post which explains how to do that using the IIS.

  • Start IIS Manager (INETMGR from the start menu works for me)
  • Navigate to desired site in the Connections tree
  • Open Output Caching
  • Edit Feature Settings
  • Uncheck Enable cache and Enable kernel cache
  • If you cannot save changes, make sure your web.config file is not marked read only
  • IISRESET is required for the changes to take place

This is the original post, which mentions that it is relevant for IIS 7.5 (in Windows 7) https://forums.iis.net/t/959070.aspx?How+do+you+disable+caching+in+IIS+

One of the things I tried before that was adding .html and .js in Output Caching, and checking "Prevent All Caching". So if it doesn't work after the IISRESET, try that, though I'm not sure it is actually required.

EDIT:

If it does not work, still in the IIS go to HTTP Response Headers and add new actions:

  1. Name: cache-control, Value: no-cache

  2. Name: expires, Value: 0

Upvotes: 0

Eonasdan
Eonasdan

Reputation: 7765

To expand on @Ramesh's answer:

to force a reload of the js file, instead of the cache, use this html:

<script src="js/config.js?v=42" type="text/javascript"></script>

The next time you make changes to that file just +1 the v. This also works with css files by the way.

Upvotes: 14

Steve
Steve

Reputation: 8640

I agree with all the other answers. 304 is not an error and there are many reasons why this behavior is correct.

That being said, there is a simple "hack" you can use. Simply attach a unique URL parameter to the JS call.

var timestamp = +new Date;
var url = "http://mysite.com/myfile.js?t=" + timestamp;

Again, this is a hack. Performance wise, this is horrible.

Upvotes: 5

user123444555621
user123444555621

Reputation: 152956

You need to set script.src = scripts[loaded]; after adding the onreadystatechange/onload handlers. Otherwise the event is going to fire before the handlers are added, since the cached version loads instantly.

Upvotes: 0

Ramesh
Ramesh

Reputation: 13266

Caching is an important for performance reasons. I would recommend you pass a version number in your query string and with every update, increment the version number. This will force the browser to resend the request and it will load from cache if it already has the same version.

Upvotes: 11

Boris Bachovski
Boris Bachovski

Reputation: 662

<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">  

Add this into your HTML HEAD.

Upvotes: 3

Related Questions