[Javascript] 阻止RequireJS缓存所需的脚本


Answers

不要为此使用urlArgs!

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

在开发过程中使用正确的HTTP标头为您的JavaScript资源提供服务以禁用缓存。

使用require的urlArgs意味着您设置的任何断点在刷新时都不会被保留; 您最终需要在代码中的任何位置放置debugger语句。 坏。 在使用git sha进行生产升级期间,我使用urlArgs来缓存资源清除资产; 那么我可以设置我的资产永久缓存并保证永远不会有陈旧的资产。

在开发过程中,我使用复杂的mockjax配置来嘲讽所有ajax请求,然后我可以使用10行python http服务器以全 JavaScript模式提供我的应用程序, 并关闭所有缓存 。 这已经扩展到一个相当大的“企业级”应用程序,拥有数百个安静的web服务端点。 我们甚至有一位签约设计师,他可以与我们的真实生产代码库一起工作,而无需让他访问我们的后端代码。

Question

RequireJS似乎在内部做了一些需要JavaScript文件的缓存。 如果我对其中一个必需的文件进行了更改,则必须重命名该文件才能应用更改。

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

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

跨平台解决方案:

我现在在开发过程中使用urlArgs: "bust=" + (new Date()).getTime()用于自动缓存清除, urlArgs: "bust=v2"用于生产的urlArgs: "bust=v2" ,其中我在推出后增加硬编码版本num一个更新的必需脚本。

注意:

@Dustin Getz在最近的回答中提到Chrome开发人员工具将在调试过程中在JavaScript文件不断刷新时跳出断点。 一种解决方法是编写debugger; 在代码中触发大多数Javascript调试器中的断点。

服务器特定解决方案:

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




这个问题有一个简单的解决方案,所以你可以为每个模块加载一个唯一的版本号。

您可以保存原始的requirejs.load函数,用您自己的函数覆盖它,并再次将修改后的url解析为原始的requirejs.load:

var load = requirejs.load;
requirejs.load = function (context, moduleId, url) {
    url += "?v=" + oRevision[moduleId];
    load(context, moduleId, url);
};

在我们的构建过程中,我使用“gulp-rev”构建了一个清单文件,其中包含所有正在使用的模块的所有修订版本。 我的大嘴巴任务的简化版本:

gulp.task('gulp-revision', function() {
    var sManifestFileName = 'revision.js';

    return gulp.src(aGulpPaths)
        .pipe(rev())
        .pipe(rev.manifest(sManifestFileName, {
        transformer: {
            stringify: function(a) {
                var oAssetHashes = {};

                for(var k in a) {
                    var key = (k.substr(0, k.length - 3));

                    var sHash = a[k].substr(a[k].indexOf(".") - 10, 10);
                    oAssetHashes[key] = sHash;
                }

                return "define([], function() { return " + JSON.stringify(oAssetHashes) + "; });"
            }
        }
    }))
    .pipe(gulp.dest('./'));
});

这将生成一个带修订号的AMD模块moduleNames,它被包含在main.js中的'oRevision'中,其中您覆盖了前面显示的requirejs.load函数。




受到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>

main.js的开始部分如下所示:

require.config({
    baseUrl: '/js',
    urlArgs: 'bust=@Revision@',
    ...
});



我不建议使用' urlArgs '来缓存使用RequireJS。 因为这不能完全解决问题。 即使您只更改了单个资源,更新版本号也会导致下载所有资源。

为了解决这个问题,我推荐使用像'filerev'这样的Grunt模块来创建版本号。 最重要的是,我在Gruntfile中编写了一个自定义任务,以便在需要时更新修订号。

如果需要,我可以分享此任务的代码片段。




在我的情况下,我想每次点击时加载相同的表单,我不希望我对文件所做的更改保持不变。 它可能与这篇文章无关,但这可能是客户端的一个潜在解决方案,无需为require设置配置。 不要直接发送内容,您可以制作所需文件的副本并保持实际文件不变。

LoadFile(filePath){
    const file = require(filePath);
    const result = angular.copy(file);
    return result;
}



我从AskApache取出这段代码,并将其放入本地Apache网络服务器的独立.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>

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