RequireJS似乎在内部做了一些事情,缓存所需的javascript文件。如果我对所需的文件之一进行了更改,我必须重命名该文件,以便应用更改。

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

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

跨平台解决方案:

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

注意:

@Dustin Getz在最近的回答中提到,当Javascript文件不断刷新时,Chrome开发工具将在调试过程中删除断点。一个解决方法是编写调试器;在大多数Javascript调试器中触发断点。

特定于服务器的解决方案:

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


当前回答

动态解决方案(不含urlArgs)

对于这个问题,有一个简单的解决方案,这样您就可以为每个模块加载唯一的修订号。

您可以保存原始需求。加载函数,用自己的函数覆盖它,并将修改后的url解析为原始需求。负载:

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

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

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('./'));
});

这将生成一个带有修订号到moduleNames的amd模块,它被包含在main.js中的'oRevision'中,在那里你可以覆盖requirej。加载函数如前所示。

其他回答

受到require.js data-main上的过期缓存的启发,我们用以下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@',
    ...
});

快速解决开发问题

对于开发,你可以在Chrome开发工具中禁用缓存(为网站开发禁用Chrome缓存)。缓存禁用只发生在开发工具对话框打开时,所以您不必担心在每次常规浏览时切换此选项。

注意:在生产环境中使用'urlArgs'是合适的解决方案,这样用户就可以获得最新的代码。但这使得调试变得困难,因为chrome每次刷新都会使断点失效(因为它每次都是一个“新”文件)。

这是对@phil mccull接受的回答的补充。

我使用了他的方法,但我也通过创建一个T4模板来自动运行预构建过程。

预构建命令:

set textTemplatingPath="%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
if %textTemplatingPath%=="\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe" set textTemplatingPath="%CommonProgramFiles%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
%textTemplatingPath% "$(ProjectDir)CacheBuster.tt"

T4模板:

生成的文件:

在require.config.js加载之前存储在变量中:

require.config.js中的引用:

这是我在Django / Flask中如何做到的(可以很容易地适应其他语言/ VCS系统):

在config.py中(我在python3中使用这个,所以你可能需要调整python2中的编码)

import subprocess
GIT_HASH = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')

然后在模板中:

{% if config.DEBUG %}
     require.config({urlArgs: "bust=" + (new Date().getTime())});
{% else %}
    require.config({urlArgs: "bust=" + {{ config.GIT_HASH|tojson }}});
{% endif %}

不需要手动构建过程 应用程序启动时只运行git rev-parse HEAD一次,并将其存储在配置对象中

我从AskApache中获取了这段代码,并将其放入本地Apache web服务器的一个单独的.conf文件中(在我的情况下是/etc/apache2/ others/preventcache .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的方法。