使用requirejs时怎么解决文件版号和增量更新的问题
发布于 5 年前 作者 hellopao 29255 次浏览 最后一次编辑是 3 年前 来自 问答

有成熟的解决方案吗?

8 回复

看你前后端用什么技术了,我知道的大概有3种情况。 在这三种情况之前,首先要说的是requirejs对依赖增加hash的方式是通过参数urlArgs: 'ver='v{version}require.config统一增加的,就我所知似乎不能单独对每个模块设置 (但可能是我错了),即每次都得批量更新版本号。

1.如果你采用过requirejs,且前后端分离,前端采用yeoman构建,那么只要找到相应的质量高的requirejs的generator,无论是gulp还是grunt, 其yeoman的generator应该已经处理好文件缓存增量更新的问题了。 2.假使前后端分离,前端由gulp/grunt集成,文件版本号增量更新,用下面几个插件就能处理的比较完美: gulp-rev gulp-rev-all gulp-useref (grunt也能找到类似的) 其中gulp-rev,计算文件hash值,gulp-useref对html内特定注解标签下的内容合并重写,gulp-rev-all会考虑css引用图片hash值改变的情况从而更新css文件hash。 等等总之只要去找总能通过gulp/grunt解决这个问题。 3.如果你使用rails(ruby)等前端友好框架,可能会有流行的解决方案,如果不幸用了老旧前端不友好的框架SpringMVC(java),用gulp对jsp重编译比较蛋疼。。我不知道有没有相应的插件,如果没有你只能在后台维持这个版本号变量,对页面所有静态资源添加这个后缀,类似下面的代码:

	var require = {
    	baseUrl: '/Content',
    	urlArgs: 'ver='+${static_resource_version},
   		paths: {...},
		deps: ['scripts/home/about']
	}
	<script src="/Content/bower_components/requirejs/require.js?ver=${static_resource_version}" async></script>

其中path之内的所有脚本,以及deps内的入口脚本,都会被追加urlArgs,只是这样还无法达到最理想增量更新就是了。。。 此外,对于文件版本号的后缀args我也推荐使用git commit的hash值。

@abruzzihraig 感谢回复。最近在搞这个问题,搜索了一圈,都没有解决方案,甚至都没人提过,难道这个不是问题吗。 我们构建工具用的gulp,你提到的那些插件我自己都有写过类似的,但这个并不能解决这个问题。 目前我在试验的方案是,先扫一遍所有的js文件,生成一个依赖关系映射。然后将映射关系里的value替换成真实文件的路径加版本号,key替换成真实的文件路径。然后写回到require.config里去。 类似下面这样: require.config({ baseUrl:"…/xx/js", paths:{ “aa”:"./aa/", “bb”:"./bb/" }, map:{ “*”:{ “aa/xxx”:"./aa/xxx.js?v=r3e3es", “bb/yy”:"./bb/yy.js?v=t3w3es", “zz”:"…/xx/js/zz.js?v=w24d3w" } } });

@hellopao 我尝试了你的tricky方案,发现有问题,看了requirejs文档有下面几句:

This feature only works well for scripts that are real AMD modules that call define() and register as anonymous modules. Also, only use absolute module IDs for map config. Relative IDs (like ‘…/some/thing’) do not work.

所以如果通过shim引入的第三方非AMD的库,这么做也会很尴尬。。。

@abruzzihraig 我上面提的后面试了确实不可行,不过另外想办法解决了。requirejs原先config.urlArgs可以用来添加版本号信息,但是是针对所有文件。我改了他源码,config.urlArgs可以是一个方法,再维护一个版本信息配置,这样就可以对每个文件用不同版本号了。代码如下:

		if (!config.urlArgs) {
            return url;
        }

        if (typeof config.urlArgs === 'string') {
            return url + ((url.indexOf('?') === -1 ? '?' : '&') + config.urlArgs);
        }

        if (isFunction(config.urlArgs)) {
            var urlArgs;
            try {
                urlArgs = config.urlArgs.call(config, moduleName, url);
            } catch (e) {
                urlArgs = "";
            }

            return url + ((url.indexOf('?') === -1 ? '?' : '&') + urlArgs);
        }

已经提了pull request,希望会被合并。

用grunt吧,根据文件内容生成MD5值来作为版本号。

coolie 吧,构建之后(生产环境)自动更新版本号。

@hellopao 现在我想在给每个js文件加上版本号,来清缓存,但是要在每个入口的config中修改urlArgs的值,有没有方法可以改一个地方就能让项目里面所有config中的urlArgs的值都改变。我看上面有用静态变量的,怎么声明啊,我声明了了全局变量,直接就报错了。 求大神指点迷津。

回到顶部