阻止JavaScript和HTML从缓存中加载

9
我正在构建一个单页JavaScript应用程序,当应用程序启动时,我使用一个单独的JavaScript文件动态加载所有需要的其他文件。当我刷新页面时,根据Firebug,我的HTML页面以及JavaScript页面将会以304未修改错误加载,导致我的JavaScript停止工作。
我知道这是由于浏览器缓存造成的,但是我该怎么避免呢?我使用单个脚本调用来加载初始的HTML页面。
<script src="js/config.js" type="text/javascript"></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);
    }
};

我知道Gmail使用cookie来防止这种情况发生。有人知道如何采用这种方法吗?我应该在服务器上设置Cookie,然后在每次页面加载/刷新时使用JS检查它,并且如果Cookie告诉我页面是从缓存加载的,就使用类似window.location.refresh()的方式重新加载页面吗?


不要刷新页面,应该重新加载。 - Boris Bachovski
我不能期望应用程序的用户知道不要刷新。这是一个需要解决的错误,而不是在浏览器中绕过它。 - ryandlf
“304 Not Modified” 不是错误。 - user123444555621
不应该影响JavaScript文件没有重新请求。它们仍然会被加载。您是否监听了正确的事件以重新初始化页面? - David-SkyMesh
8个回答

13

@Ramesh的答案上进一步解释:

如果想要强制重新加载js文件而不是使用缓存,请使用以下html代码:

<script src="js/config.js?v=42" type="text/javascript"></script>
下次您对该文件进行更改时,只需将 v 增加1即可。顺便说一下,对于 CSS 文件也适用。

这适用于在HTML中加载的脚本文件,但如何防止ES6模块的缓存?即使每次使用不同的GET参数加载主文件,由此文件导入的模块也会被缓存。 - Samuel Gfeller

11

为了提高性能,缓存是非常重要的。建议您在查询字符串中传递版本号,并在每次更新时递增版本号。这将强制浏览器重新发送请求,并且如果已经存在相同的版本,则会从缓存中加载。


5
我同意其他回答的结论。304不是一个错误,有很多原因可以解释这种行为的正确性。
话虽如此,你可以使用一个简单的"hack"。只需要将一个唯一的URL参数附加到JS调用即可。
var timestamp = +new Date;
var url = "http://mysite.com/myfile.js?t=" + timestamp;

这只是一种hack。就性能而言,这是极其糟糕的。


我在我的动态脚本加载工具中使用这种方法,效果很好。但是在这种情况下,考虑到它涉及应用程序的核心部分,我正在寻找一种稍微更高效的方法。 - ryandlf

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

将以下代码添加到HTML HEAD中。

1
这并不会阻止浏览器缓存和传递304未修改的错误。 - ryandlf
304 Not Modified只是一个“你应该有缓存的”响应,它不是一个错误。 - David-SkyMesh

1

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

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


1
我建议使用JavaScript生成一个随机数,使用Math.random乘以它,然后使用Math.floor返回其整数。然后,我会将这个数字作为变量添加到URL中。由于每次页面加载时数字都会改变,因此文件不应该被缓存。
<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>

我认为这会在每次加载页面时进行额外的计算。最好只是禁用缓存。 - Fakipo
1
这对我有用,只是改变了一下,把<script id="myScript"></script>放在计算之上。否则,getElementById会失败。 - Vilda

0

在添加 onreadystatechange/onload 处理程序之后,您需要设置 script.src = scripts[loaded];。否则,由于缓存版本会立即加载,事件将在添加处理程序之前触发。


0

经过数月的缓存问题挣扎,尝试了几乎所有方法(包括使用参数更改URL的脚本),我找到了一篇文章,解释了如何使用IIS来解决这个问题。

  • 启动IIS管理器(从开始菜单中的INETMGR适用于我)
  • 在连接树中导航到所需站点
  • 打开输出缓存
  • 编辑功能设置
  • 取消选中启用缓存和启用内核缓存
  • 如果您无法保存更改,请确保您的web.config文件未标记为只读
  • 需要执行IISRESET才能使更改生效

这是原始帖子,提到它适用于IIS 7.5(在Windows 7中) https://forums.iis.net/t/959070.aspx?How+do+you+disable+caching+in+IIS+

之前我尝试过的一件事是在输出缓存中添加 .html 和 .js,并勾选“防止所有缓存”。所以如果在 IISRESET 后它仍然不起作用,请尝试这样做,尽管我不确定是否实际上需要。

编辑:

如果还是不行,在 IIS 中继续前往 HTTP 响应标头并添加新操作:

  1. 名称:cache-control,值:no-cache

  2. 名称:expires,值:0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接