在require.js的data-main中如何清除缓存

43

我正在使用 require.js 和 r.js 打包我的 AMD 模块。我是通过以下语法来使用 jQuery 和 RequireJS 的:

<script data-main="/js/client" src="/js/external/require-jquery.js"></script>

这些内容在打包前和打包后都很好用,但我经常遇到Chrome和移动Safari保留了client.js的缓存版本的问题。我想给client.js添加一个CacheBuster,但是我似乎无法使用上述语法来实现它。

我尝试过一些变化:

<script data-main="js/client.js?b=busted" src="/js/external/require-jquery.js"></script>

但现在需要从/获取client.js,而不是从/js获取,因此会出现404错误。

我还尝试添加

urlArgs : "bust="+new Date().getTime()

尝试使用require.config,但它似乎没有任何效果。

我还尝试将相同的值添加到app.build.js中,但是当它在那里时,r.js不再连接我的js文件,只是混淆它们。

如何正确地打破require.js data-main脚本缓存的语法?


data-main="/static/code/main.js?git_sha=ae9f10b520" 对我有效。 - Bob Stein
2个回答

76

你是如何定义 require.config 的呢?我认为要让它在导入 require.js 之前生效,你需要这样编写代码:

<script type="text/javascript">
    var require = {
        baseUrl: "/scripts/",
        waitSeconds: 15,
        urlArgs : "bust="+new Date().getTime()
    };
</script>
<script data-main="app/main" src="/scripts/require.js"></script>

具体而言,在导入require.js之前,必须构造一个名为'require'的对象。

更新

正如Jesse在下面的评论中指出的那样,您应该对您的require{}对象进行一些增强以用于生产环境。上面的示例来源于RequireJS文档,并尽可能少地修改以回答这个问题。

以下是几个需要考虑用于生产环境的事项:

  • 不要像使用当前日期时间作为缓存破坏变量一样,应该使用来自开发环境的版本号。这允许客户端在发布之间缓存JavaScript,但会在您进行软件更新时使它们刷新其缓存。
  • Jesse还使用了require{}的能力来指定依赖关系,而不是使用脚本的data-main属性。我不知道这是否严格意义上更好,但我认为这看起来更加简洁。
  • 根据您的需求调整waitSeconds。我使用了RequireJS文档中的示例值,但您应该根据您的需求调整该值或省略它。

所以,如果您应用了这些技术,您的代码可能如下所示:

<script type="text/javascript">
    var require = {
        baseUrl: "/scripts/",
        waitSeconds: 15,
        urlArgs : "bust="+{{buildNumber}},
        deps : ['app/main']
    };
</script>
<script src="/scripts/require.js?bust={{buildNumber}}"></script>

请注意,在这种情况下,{{buildNumber}} 是由服务器提供的值。

更新2

urlArgs缓存破坏解决方案存在问题。不幸的是,您无法控制可能在您和用户Web浏览器之间的所有代理服务器。其中一些代理服务器可能被不幸地配置为在缓存文件时忽略URL参数。如果发生这种情况,则会向用户传递错误版本的JS文件。

我建议在您的Javascript文件名请求中使用buildNumber,例如buildNumber.myModule.js(前缀)或myModule.buildNumber.js(后缀)。您可以通过修改baseUrl来使用前缀样式:

baseUrl: "/scripts/buildNumber",

注意baseUrl结尾没有'/'。

你需要使用修改过的require.js来使用后缀解决方案。你可以在这里阅读更多信息:https://dev59.com/rGsy5IYBdhLWcg3wyxCi#21619359

显然,无论哪种情况,你都需要使用某种解决方案来用某种随每次发布而变化的版本号替换 buildNumber


2
谢谢!这就是我最终解决问题的方式,只是忘记回来更新了。在我的情况下,waitSeconds并不必要(它将默认为7),而我将我的bust变量设置在服务器上,这样它就会与我的应用程序版本同步。另外,我也将主要脚本定义移到了 require 配置中。 - Jesse
3
在我的情况下,require 看起来是这样的:require = { urlArgs : "b={{buildTime}}", baseUrl : "/js", deps : ['client'] },下面的 require 中没有 data-main。我还在 require 依赖项上设置了缓存破坏器,以确保彻底。 - Jesse
3
谢谢您。我必须清空Chrome缓存才能使刷新生效,不知道为什么这个信息这么难找到... - Cristiano Fontes
2
回复:“不幸的是,您无法控制可能存在于您和用户Web浏览器之间的所有代理服务器。” 如果您使用HTTPS,则不是问题。 - Greg
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - JBCP
显示剩余2条评论

-2

这是我的解决方案(紧急情况下):

  1. 在require.js中找到以下代码:

开发版本

//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/');
url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? '' : '.js'));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;

或者

生产版本

e).join("/"),h=m(d,h)){H(h)&&(h=h[0]);a.splice(0,e,h);break}d=a.join("/");d+=b||(/^data\:|\?/.test(d)||c?"":".js");
  • .js 后面添加 ?v=x.0

    url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? '' : '.js?v=1.0'));

    或者

    (/^data\:|\?/.test(d)||c?"":".js?v=1.0");


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