Stop Javascript and HTML from Loading From Cache
Asked Answered
P

8

9

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?

Plascencia answered 29/3, 2012 at 2:50 Comment(4)
Don't refresh the page, RELOAD instead.Nawrocki
I can't expect a user of the application to know not to refresh. This is a bug that needs to be solved, not worked around in the browser.Plascencia
304 Not Modified is not an error.Achromat
It shouldn't matter that the JavaScript files aren't re-requested. They'll still be loaded. Are you listening to the right event to reinitialize your page?Bourn
K
11

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.

Kath answered 29/3, 2012 at 5:10 Comment(0)
B
14

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.

Bisk answered 29/3, 2012 at 12:28 Comment(1)
This works for script files loaded in the HTML but how to prevent caching of ES6 modules? Even if the main file is loaded with a different GET-parameter each time, the modules imported by this file are cached.Fullblown
K
11

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.

Kath answered 29/3, 2012 at 5:10 Comment(0)
S
5

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.

Stapes answered 29/3, 2012 at 5:22 Comment(1)
I use this approach in my dynamic script loading utilities and it works great, but in this situation, considering it involves the centerpiece of the application, I am looking for a slightly more efficient approach.Plascencia
N
3
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">  

Add this into your HTML HEAD.

Nawrocki answered 29/3, 2012 at 2:54 Comment(2)
This does not stop the browser from caching and passing 304 Not Modified Errors.Plascencia
304 Not Modified is simply a "You should have this cached" response, it's not an error.Bourn
P
1

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

echo  " <script	src='root.js?$xn'></script>";
?>
Palecek answered 14/3, 2018 at 14:59 Comment(0)
L
1

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>
Lactary answered 16/3, 2018 at 10:38 Comment(2)
I think this will make extra calculations every time the page is loaded. better to just disable cache.Unconquerable
This worked for me with the change that <script id="myScript"></script> is above the calculation. Otherwise the getElementById fails.Sewoll
A
0

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.

Achromat answered 29/3, 2012 at 5:10 Comment(0)
C
0

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

Compiler answered 8/6, 2017 at 6:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.