





























bug1描述:
IE6部分版本,某些情况下,开启gzip的资源,会不渲染或不执行(如果是.js的话.)
会引发此bug的条件:
1. 首先,必须由a页跳转到b页面 : 即 a页面有 location.href = b页面.(点链接,form post,replace, assign等方式都会导致问题,包括target=_blank弹窗的情况)
2. b页面自身,或使用动态创建脚本(硬编码script src=xxx 也存在此问题) 的响应头中包含下面情况:
cache-control 包含下列伪指令:
(1) no-store
(2) no-cache + 其他与缓存新鲜度检验有关头共存时, 如 max-age=xxx (xxx无所谓.0 或3000都会触发,) 或 no-cache + must-revalidate 甚至是,no-cache, pre-check=0等情况..
(3) no-cache独立存在时,体现为一种不稳定情况.可能会触发.但也不是100%.仅仅是偶尔...
ps: 本bug ,与 http1.0 头域 : Pragma : no-cache ,无关. 也于是否chunked输出无关.
注意: 不配置cache-control并不写expires 同样会触发.
更神奇的是,一但,开启gzip, 则 i6会无视ETag .(ETAG,bug没有被我独立列出来.因为它的严重性并不太高..) 不会尝试2次握手.完全放弃使用本地缓存....也就是说,ie6发起请求时,不会带有 if-none-match头...
Last-Modified则无此问题.
但是要注意的是: IE6会开启gzip的情况下, 在if-Modified-Since 值中加入length = xxxx .字样. 我不确定所有的web server 在检测该值是 检验相等性,还是检测包含性.尤其是大家用nodejs写一个轻量级web server的时候.一定要注意这个问题
.务必使用 headers['if-Modified-Since']indexOf(缓存日期) > -1 的逻辑来做.
如图:

IE7+ 则无此问题..
解决办法:
1. 放弃gzip.
2. 放弃cache-control 中的 no-cache,no-store头域. 比如 单独使用max-age=0.并对不支持http1.1的老浏览器配合Expires = 一个过期时间.
ps :
1.与bug1类似的情况 还有ajax , 或动态发起的jsonp 等请求. 当某个页面有这种情景,且被请求资源开启gzip , cache-control有前面提到的那些配置.那么同一个资源(即使querystring有不同),第二次对其发起请求,就可能导致ajax readyState==4的情况不被出发,或jsonp的脚本不被执行. 解决办法同上.
2.类似的,如果多个iframe 自身就有gzip,则也会引发问题.即不渲染,甚至可能会定位到404(抓包一切正常).
msdn上的说法:
To work around this problem, you can do either of the following:
If you use a Cache-Control: no-cache HTTP header to prevent the files from caching, remove that header. In some situations, if you substitute an Expires HTTP header, you do not trigger the problem.
-or-
Do not enable HTTP compression for the script files.
显然,微软给了我们两条路,去掉no-cache头,或者使用Expires指定过期时间,强制使其过期代替no-cache, 或者别压缩. 而pre-check=0.显然可以代替Expires做到这件事.
一个常见的误区是,有些朋友收借助 cache-control ,IE定义的扩展指令来解决这个问题.参考下面的描述:
扩展指令 中一个常见的东西是 none-check post-check 和 pre-check. 这玩意是IE5被加入的. 所以如果响应头中有这几个扩展指令,那么IE就会认得他们, 我经常在一些 为了解决 cache + gzip 命中ie6 JSONP 请求,导致脚本不执行bug的方案中见到这几个扩展指令,其目的是为了让IE放弃使用本地缓存. 我倒是觉得,对IE6放弃使用gzip,是更合理的做法. 当然缺点也很明显, 如果是cdn部署静态资源.显然这样做会很困难.
关于这几个扩展指令的, 参考msdn 的描述:http://msdn.microsoft.com/en-us/library/ms533020%28VS.85%29.aspx#Use_Cache-Control_Extensions
一张图:

简单来说, 就是控制IE,如何使用本地缓存 ,如果缓存时间,超过post-check的值,就要保证下一次请求该资源,去要验证过的新鲜的.而pre-check则是超过了,就马上给个新的. no-check就无需解释了..
但这个方法本质上是无法绕过这个bug的... 所以根本原因还是 ,去掉no-cache,no-store. 或放弃压缩.
bug2 描述:
当一个页面,有多个iframe , 而每个iframe 都引入 a.js 时, 如果a.js 开启gzip ,且无论是否有缓存头,比如 Expire= xxx, Control-Cache: max-age= xxxx 的情况下
那么这个a.js就可能在某次不被执行. (请注意这个问题和 之前gzip第一个bug情形不同.上一个是no-cache出现bug. 而这个,已经和http,cache无直接关系了.当然,如果你配置了no-cache,那么这个bug也是肯定会触发的,具体原因,请看解决方案中的第三条.所以某种角度来说,这个问题,可能和第一个bug描述,仍然有间接关系.只不过,我个人测试情况是,20个iframe,如果请求的js都是不同的url,那么即使配置no-cache,也没有触发我们的bug2,但是这回带来bug3.我们会在bu3中描述它. 但如果配置no-cache,多个iframe中请求相同的url的js,那么bug2就仍然会被触发.这是因为我们预加载已经失去意义.)
分析: 大概是高并发请求时,IE共享以某个url为标签的资源的状态时,在某种特定情况下,把n个独立请求的相同资源的状态给共享了,比如把某脚本的待执行状态标为已执行过. 但是为什么,只有gzip的资源才会发生.就不得而知(更重要的是,并不直接与资源是否具备缓存能力有直接关系.). 一切都是黑盒推测.所以也做不得准...
ps: iframe 下引入多个脚本,是可以并行加载,且无视http连接数限制的。
如果a.js在 iframe中是document.write,或appendChild等动态方式.那么bug发生几率会都陡升.
如果a.js在同一个页面被引入多次,则不会有任何问题. 原因是,IE6+有一个优化策略.当同一个页面多次引入一个相同的资源时,后续资源不会走网络模块,也就是说,不会发起请求.而直接从以资源url为索引的内存中直接使用该资源. 所以就不会发生问题.
IE7+,在前面多个iframe中引入 同一个.js时,会有类似 同一页面多次引入同一.js时同样的优化策略.不发起请求. 不考虑IE7是否有gzip bug. 即使有,也会因为,没有走网络模块而绕过了gzip bug.
解决方案 :
1. 放弃缓存,比如去掉max-age= xxx,去掉Expires ,或让他们为一个过期值. 或添加 no-cache,no-store.(此项是不被推荐的,因为它只是降低bug触发几率)
2. 放弃gzip .
3. 让IE6,在top页预加载一次.js资源. 这样, 在多个iframe中. 引入的.js,会直接走cache.在后续iframe请求.js 都走cache的情况下会绕过这个bug. (如果用户是ctrl+ f5,强制刷新.都不走cache,当iframe很多,资源加载很多次时bug触发概率也会陡升,也就是说,预加载资源只能解决常规问题.一些特殊情况仍然无法绕过. 当然,普通的f5是ok的因为普通的f5,会触发IE6的优化策略.这时候其行为会像前面提到的IE7+那样,对多个相同的资源,只走一次网络模块.所以就绕过了bug,而ctrl+f5则有几个就走几次网络模块.. 更重要的是,如果想让预加载产生效果,我们就必须给资源开启缓存. 如果资源不能被缓存,则预加载就失去了意义.这是要注意的情况.)
我个人建议采用第三种. 在top页预加载一次.
为了不浪费客户端性能, 我建议使用下面的代码来进行预加载.
<!--[if IE 6.0]>
<script src="xxxx.a.js" type="text/c"></script>
<![endif]-->
这个代码的作用是,只有IE6进行预加载,而且 借助type="text/c" 让IE6只加载a.js 而不执行它....
bug3 描述
如果你的浏览器是IE6 SP2-(SP3已经修正这个问题,此问题与iframe与否,无直接关系,BUG1,BUG2,的场景,都可能触发BUG3).当你引入多个不同url的xxx.js时, 第一次后, f5刷新浏览器.那么ie就会忘记你的js的编码. 比如我们在xxx.js中输出了一些汉字.而我们引入该js,编码要么是GBxxxx或GBk,要么是utf - xx. 那么就会出现乱码,甚至是因为乱码导致js解析失败.抛出异常. 而首次访问,或ctrl+f5强制刷新,则无此问题...
解决办法:
1. 不要有no-cahce,no-store,等等.
2. 放弃gzip
3. ...... 好吧,真的没有3了..
这真是一个异常艰难的总结,但我们总要面对这些让人吐血的问题,不是么?
bug触发的条件,环境很复杂,绝大多数情况下,我们可以认为是某个资源多次被加载则触发的可能性会陡升
假设, 你是用jsonp,等方式加载数据.又需要开启gzip ,而该数据总是动态的,(即我们不希望它被任何中间环节缓存).而且,你又要保证这玩意,不会在多个iframe中存在.而仅仅服务于某一个特定页面的话, 那就记得别用Cache-Control:no-cache,no-store ,而改用Expires = 过期时间 + max-age=0 来搞定.
假设我们期待某些资源总是被缓存的. 又不得不开启gzip ,而资源,又总是出现在一些iframe中, 那么记得.在top页, 预加载他们是个不错的选择.
否则,对ie6 放弃 gzip 吧,兄弟们. gzip对于ie6来说,真是万恶之源啊...(nginx 针对ie6,不开启gzip,很简单,只要一行短短的配置指令即可.如果需要,请查文档.nginx真的很贴心.可以方便的针对某一种ua,开启或关闭某些东东.)
最后不得不提的是.我之前一再说过一个词,就是不渲染. 那么解释下,不渲染是指,如果资源是一个html. 那么这个html里的任何东西,都不会渲染. 内部资源也不会加载. IE6,SP2-遇到编码问题,也是一样的....
好吧. 最后 IE6 SUCKS !!! ....
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。