今天上午同事反馈一个诡异的问题:
某项目中动态引用的js文件每次请求都会带上临时的时间戳参数,导致缓存无效。非常影响用户体验,因为每次访问都会重新加载大量的js文件
同事找了半天找不到是在哪里添加了时间戳参数,我抽出时间分析了下,经过步步排查,找到问题所在的代码:
1 | var JS_PATH_LIST = [ |
这段代码看上去没毛病,可实际在执行过程中的请求如下:
所有js文件的请求都额外加上了类似”_=1659089706720“的时间戳参数。
翻遍所有的代码,都没有找出是谁在什么地方添加了这个参数,只好逐个击破。
逐步去掉所有与此函数无关的代码,发现问题依旧会存在,最后只留了最简单的示例代码,问题还是存在,只好怀疑jQuery干了什么事!
把疑问告诉同事,同事一会发来一个参考:
网上给出的方案是:
jQuery.ajaxSetup中设置cache为true
再次查看我们的网络请求,发现确实通过jQuery.append()方式添加的js文件,都是xhr请求;而通过原生JavaScript的appendChild添加的js文件,则是常规的Script请求。
这就充分说明了,jQuery认为这是一个ajax请求,为了防止缓存问题,自动添加了时间戳参数(查看代码也是如此)。而在我们的这个场景中,我们是不想每次都重新请求的。
但是单纯的对我们的场景设置为true会不会有影响呢?查看jQuery官方文档:
cache (default:
true, false for dataType 'script' and 'jsonp'
)Type: Boolean
If set to
false
, it will force requested pages not to be cached by the browser. Note: Settingcache
to false will only work correctly with HEAD and GET requests. It works by appending “_={timestamp}” to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.
从这段话看出来,属性cache默认为true,但当dataType为script或jsonp时,该属性则默认为false。
而我们的情况,正好是后者,dataType为script,cache为false。所以设置cache为true,强制所有的请求设置了缓存。
但很明显这样做了的话,对于jsonp的请求可能会有缓存问题。好在我们并没有使用json请求,问题算勉强解决。
不过有另外一个问题还没想明白,为什么jQuery.append的angularjs文件可以正常运行,但是通过原生document.appendChild添加的angular文件却执行报错,始终报module not found,网络请求里看到的js文件都是正常请求了的。