防止RequireJS缓存所需的脚本

Bum*_*2na 296 javascript jquery requirejs

RequireJS似乎在内部执行缓存所需javascript文件的操作.如果我对其中一个必需文件进行了更改,则必须重命名该文件才能应用更改.

将版本号作为查询字符串参数附加到文件名末尾的常见技巧不适用于requirejs <script src="jsfile.js?v2"></script>

我正在寻找的是一种方法来防止这种内部缓存RequireJS所需的脚本,而不必在每次更新时重命名我的脚本文件.

跨平台解决方案:

我现在正在urlArgs: "bust=" + (new Date()).getTime()开发和urlArgs: "bust=v2"生产期间用于自动缓存清除,我在推出更新的所需脚本后增加硬编码版本num.

注意:

@Dustin Getz在最近的回答中提到,Chrome Developer Tools会在调试期间丢弃断点,此时Javascript文件会不断刷新.一种解决方法是编写debugger;代码以在大多数Javascript调试器中触发断点.

服务器专用解决方案:

对于可能更适合您的服务器环境(如Node或Apache)的特定解决方案,请参阅下面的一些答案.

Phi*_*ick 455

RequireJS可以配置为每个脚本URL附加一个值以进行缓存清除.

从RequireJS文档(http://requirejs.org/docs/api.html#config):

urlArgs:附加到RequireJS用于获取资源的URL的额外查询字符串参数.在未正确配置浏览器或服务器时缓存半身像最有用.

例如,将"v2"附加到所有脚本:

require.config({
    urlArgs: "bust=v2"
});
Run Code Online (Sandbox Code Playgroud)

出于开发目的,您可以通过附加时间戳强制RequireJS绕过缓存:

require.config({
    urlArgs: "bust=" + (new Date()).getTime()
});
Run Code Online (Sandbox Code Playgroud)

  • 非常有帮助,谢谢.我正在使用`urlArgs:"bust ="+(new Date()).getTime()`用于开发期间的自动缓存清除和`urlArgs:"bust = v2"`用于生产我增加硬编码版本号在推出更新的必需脚本之后. (46认同)
  • 我认为每次破坏缓存都是一个糟糕的主意.不幸的是,RequireJS没有提供另一种选择.我们确实使用urlArgs但不使用随机或时间戳.相反,我们使用当前的Git SHA,只有在我们部署新代码时才会改变. (11认同)
  • ...作为性能优化器,您可以使用Math.random()代替(new Date()).getTime().它更美观,而不是创建对象和更快一点http://jsperf.com/speedcomparison. (9认同)
  • 如果提供"v2"字符串本身的文件被缓存,那么这个"v2"变体如何在生产中工作?如果我发布一个新的应用程序投入生产,增加"V3"是不会做任何事情,因为应用程序高高兴兴地保持与缓存v2的文件,包括旧的配置与V2`urlArgs`工作. (5认同)
  • 你可以把它缩小一点:`urlArgs:"bust ="+(+ new Date)` (2认同)

Dus*_*etz 54

不要使用urlArgs!

需要脚本加载尊重http缓存标头.(脚本加载了动态插入<script>,这意味着请求看起来就像任何旧资产被加载一样.)

使用正确的HTTP标头为您的javascript资产提供服务,以在开发过程中禁用缓存.

使用require的urlArgs意味着您设置的任何断点都不会在刷新时保留; 您最终需要debugger在代码中的任何位置放置语句.坏.我使用urlArgsgit sha在生产升级期间用于缓存资源的缓存; 然后我可以设置我的资产永远缓存,并保证永远不会有陈旧的资产.

在开发中,我使用复杂的mockjax配置模拟所有ajax请求,然后我可以使用10行python http服务器以 javascript-only模式提供我的应用程序,并关闭所有缓存.这已经扩展到了一个包含数百个宁静的Web服务端点的相当大的"企业"应用程序.我们甚至有一个签约设计师,他可以使用我们真实的生产代码库,而无需让他访问我们的后端代码.

  • @ JamesP.Wright,因为(至少在Chrome中)为页面加载时发生的事情设置断点,然后单击刷新,因为URL已更改且Chrome已删除断点,因此未点击断点.我很想知道一个仅限客户的解决方法. (8认同)
  • 您可以在Chrome中禁用缓存以解决开发过程中的调试问题:http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development (5认同)
  • +1来!!!不要在生产中使用urlArgs !!! .想象一下,您的网站有1000个JS文件(是的,可能!),它们的负载由requiredJS控制.现在你发布v2或你的网站,只有少数JS文件被更改!但是通过添加urlArgs = v2,您强制重新加载所有1000个JS文件!你将支付大量的流量!只应重新加载修改后的文件,所有其他文件应以状态304(未修改)进行响应. (5认同)
  • 对于在节点上使用http-server的任何人(npm install http-server).您还可以使用-c-1禁用缓存(即http-server -c-1). (2认同)

JBC*_*BCP 24

urlArgs解决方案存在问题.遗憾的是,您无法控制可能位于您和用户的Web浏览器之间的所有代理服务器.遗憾的是,其中一些代理服务器配置为在缓存文件时忽略URL参数.如果发生这种情况,您的JS文件的错误版本将传递给您的用户.

我终于放弃并直接在require.js中实现了我自己的修复.如果您愿意修改requirejs库的版本,则此解决方案可能适合您.

你可以在这里看到补丁:

https://github.com/jbcpollak/requirejs/commit/589ee0cdfe6f719cd761eee631ce68eee09a5a67

添加后,您可以在require配置中执行以下操作:

var require = {
    baseUrl: "/scripts/",
    cacheSuffix: ".buildNumber"
}
Run Code Online (Sandbox Code Playgroud)

使用构建系统或服务器环境替换buildNumber版本ID /软件版本/喜欢的颜色.

像这样使用require:

require(["myModule"], function() {
    // no-op;
});
Run Code Online (Sandbox Code Playgroud)

将导致需要请求此文件:

http://yourserver.com/scripts/myModule.buildNumber.js
Run Code Online (Sandbox Code Playgroud)

在我们的服务器环境中,我们使用url重写规则来去除buildNumber,并提供正确的JS文件.这样我们实际上不必担心重命名所有JS文件.

该补丁将忽略指定协议的任何脚本,并且不会影响任何非JS文件.

这适用于我的环境,但我意识到一些用户更喜欢前缀而不是后缀,应该很容易修改我的提交以满足您的需求.

更新:

在pull请求讨论中,requirejs作者建议这可以作为修订号前缀的解决方案:

var require = {
    baseUrl: "/scripts/buildNumber."
};
Run Code Online (Sandbox Code Playgroud)

我没试过这个,但暗示是这会请求以下网址:

http://yourserver.com/scripts/buildNumber.myModule.js
Run Code Online (Sandbox Code Playgroud)

对于可以使用前缀的许多人来说,这可能非常有效.

以下是一些可能的重复问题:

RequireJS和代理缓存

require.js - 如何在URL中设置所需模块的版本?


dvt*_*ver 19

require.js data-main上Expire缓存的启发,我们使用以下ant任务更新了我们的部署脚本:

<target name="deployWebsite">
    <untar src="${temp.dir}/website.tar.gz" dest="${website.dir}" compression="gzip" />       
    <!-- fetch latest buildNumber from build agent -->
    <replace file="${website.dir}/js/main.js" token="@Revision@" value="${buildNumber}" />
</target>
Run Code Online (Sandbox Code Playgroud)

main.js的开头看起来像:

require.config({
    baseUrl: '/js',
    urlArgs: 'bust=@Revision@',
    ...
});
Run Code Online (Sandbox Code Playgroud)


Lou*_*uis 11

在生产中

urlArgs 可能会导致问题!

requirejs的主要作者不喜欢使用urlArgs:

对于已部署的资产,我更喜欢将整个构建的版本或哈希作为构建目录,然后只需修改baseUrl用于项目的配置以使用该版本化目录作为baseUrl.然后没有其他文件发生变化,这有助于避免一些代理问题,因为它们可能无法缓存带有查询字符串的URL.

[造型我的.]

我遵循这个建议.

开发中

我更喜欢使用智能缓存可能经常更改的文件的服务器:在适当的时候发出Last-Modified并响应If-Modified-Since304 的服务器.即使是基于Node的express设置服务静态文件的服务器,也可以直接使用.它不需要对我的浏览器做任何事情,也不会破坏断点.


小智 7

我从AskApache中获取了这个片段并将其放入我本地Apache Web服务器的单独.conf文件中(在我的案例中为/etc/apache2/others/preventcaching.conf):

<FilesMatch "\.(html|htm|js|css)$">
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>
</FilesMatch>
Run Code Online (Sandbox Code Playgroud)

对于开发,这可以正常工作,无需更改代码.至于制作,我可能会使用@ dvtoever的方法.


Dee*_*Joy 6

快速修复开发

对于开发,您可以在Chrome开发者工具中禁用缓存(禁用Chrome缓存以进行网站开发).仅当开发工具对话框处于打开状态时才会禁用缓存,因此您无需担心每次进行常规浏览时都会切换此选项.

注意:使用' urlArgs '是正确的生产解决方案,以便用户获得最新的代码.但它使调试变得困难,因为chrome会在每次刷新时使断点无效(因为每次都会提供一个"新"文件).