IE7和IE8无法随机加载外部脚本

7
一旦DOM准备就绪,我会动态添加元素到头部。然而,在IE7和IE8中,我得到了不一致的结果(其他所有浏览器都没有问题)。
每隔几次加载页面(缓存或未缓存),IE 7/8将在样式表中删除一些CSS规则。我的动态样式表中的1或2个不会加载。IE通常会忽略同样的1或2个样式表 - 即使开发者工具栏显示它们已添加到头部!
样式表本身显示为元素出现在最终的DOM中,但其中一些规则被应用(尽管每隔几次重新加载时它们都被应用,没有任何问题)。
在我的职位上,我没有从编写代码的奢侈(CMS限制)- 我只能从正文动态插入,这可能是问题所在。 更新:这是我使用的代码(位于中)来插入样式表:
document.observe('dom:loaded', function() { // Using Prototype.js

// Add stylesheets
// addStylesheet('cite.css', 'head'); // Contains no webfont/@font-face rules
// addStylesheet('type.css', 'head'); // Contains webfont family name references*
// addStylesheet('flex.css', 'head'); // Responsive rules with @media queries
// addStylesheet('anm8.css', 'head'); // Some minor positional CSS for home page
// addStylesheet('gothic-cite.css', 'head'); // *Contains @font-face config
// addStylesheet('stag-cite.css', 'head'); // *Contains @font-face config

addStylesheet('all.css', 'head'); // Contains ALL content from above in 1 file

function addStylesheet(cssname, pos2)
{
    var th2 = document.getElementsByTagName(pos2)[0];
    var s2 = document.createElement('link');
    s2.setAttribute('type', 'text/css');
    s2.setAttribute('href', cssname);
    s2.setAttribute('media', 'screen');
    s2.setAttribute('rel', 'stylesheet');
    th2.appendChild(s2);
}

});

如建议所示,即使我将所有规则合并到一个样式表中(这是我不喜欢的),IE 7/8在某些规则上仍然会像描述的那样翻转,并且页面显示不同。
进一步检查时,我还从样式表中删除了所有的@font-face和引用的font-family: "webfont-name"规则,但是相同的行为仍然存在。因此,我们可以排除webfonts是问题的原因。
您可以通过使用IE8访问以下内容并多次刷新/单击导航来查看异常情况。 IE8似乎完全随机地丢弃这些样式。然而,在本地构建的控件页面中,所有样式每次都能正确加载。

Live Page (with problems)

https://www.eiseverywhere.com/ehome/index.php?eventid=31648&tabid=50283

  1. PHP-based CMS prints out XHTML on page load (template content mixed w/user content)
  2. Prototype.js is loaded and initialized by default on page load
  3. CMS proprietary scripts.js file is parsed on page load
  4. My scripts run when DOM is loaded, essentially replacing body.innerHTML CMS fluff-HTML with just the HTML I want, then adds stylesheets to <head>.
  5. For lte IE 8, CSS extension plugins (selectivizr.js, html5.js, and ie-media-queries.js) are loaded within the <body> via conditional comments. Not sure if they wait for DOM:loaded...
  6. The CMS WYSIWYG editor converts all carriage-returns to empty <p> tags, resulting in elements like <section> being contained inside broken <p> tags, and extra <p></p> tags being created where whitespace is expected. Only lt IE 8 seems to choke on this, however, so I added the following CSS rules to remedy this:

    :not(.ie7) p { display: none; }
    .ie7 p { display: inline; }
    article p { display: block !important; }
    
  7. I should note that the external stylesheets here are being pulled from the same domain, but each time they are re-uploaded, a new MD5-based URL is generated for the file. I'm not sure if previous revisions to the file (or previous files) are still available by their previous URLs. This isn't likely to be the problem though, since the newly created all.css stylesheet is still dropping rules that have been in the file from the start.

控制页面(完美运行)

http://client.clevelanddesign.com/CD/IDG/CITE/home.html

  1. 纯XHTML文档 - 没有PHP。
  2. 为了IE8及以下版本,使用jQuery而不是Prototype。
  3. 所有资源(样式表)在页面加载时都存在于中 - 没有动态插入。
  4. 对于lte IE 8,CSS扩展插件(selectivizr.js、html5.js和ie-media-queries.js)会被本地初始化。

重新表述的问题:

您认为以下哪些差异可能导致在Live页面上加载IE 7/8时样式反复出现?我个人怀疑是竞争条件问题,或者是Prototype.js和其他CMS脚本搞砸了事情(不幸的是没有办法从页面中清除它们)。

PS:我已经尝试使用IE的createStylsheet()函数,但无济于事。

更新 - 在IE8中工作/不工作的屏幕截图

IE8:正确加载时的DOM代码: IE8: DOM code when loaded correctly

IE8:DOM 代码在正确加载时: IE8:DOM 代码在未正确加载时

也许这里的一些内容能够提供帮助:http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/10164546.aspx - Sparky
我检查了一下,所有的样式表合并后,我只使用了大约200个规则,这些外部样式表远远没有接近32位限制。所以不是这个问题 :/ - atwixtor
我怀疑这是某些规则的问题,而不是表格本身的问题。这将是一个有趣的测试:将 type.cssflex.css 合并成 cite.css,看看是否有任何不同。它应该完全相同。 - Sparky
@Sparky672 - 我将所有的样式表合并成一个all.css,发现了两件有趣的事情。1:所有规则都能够完美加载,包括原本分开的每个CSS文件。2:Web字体规则(@font-face {...})和引用其中给定的font-family名称的规则在50%的时间内不存在,并且与上述问题中描述的IE 7/8的不一致加载模式相同。1:合并它们不应该对IE选择应用规则产生影响吗?2:为什么IE会时不时地删除@font-face规则? - atwixtor
我想说这里有两个问题:IE在使用多个动态添加的样式表时存在竞争条件问题;以及IE在应用@font-face规则时存在问题。但在确认这两个问题是否相关之前,我想测试当所有@font-face规则已被删除(供测试使用)时,多个样式表(按照原始配置)如何工作。如果我能够在IE中得到一致的页面加载(其中应用了所有@font-face样式),那么我可以说这两个问题源自同一个@font-face差异(在这种情况下,我将更改此问答标题)。 - atwixtor
显示剩余6条评论
2个回答

1

我已经确定了发生的情况,但仍不知道flip-flop的原因:

selectivizr.js在每隔几个页面加载时无法正确加载。

所有使用CSS3选择器的规则都需要在IE 7/8中应用该脚本。因此,当IE 7/8未能正确加载selectivizr.js时,这些规则将被忽略。这些规则肯定包括Web字体引用,以及错误的<p>显示属性。

为了提醒大家,这些辅助JS脚本通常会在初始页面加载时(从<body>内部)正常加载,然后我的脚本替换<body>内容(包括该脚本引用)。因此,有可能会初始化两次(可以有人证实吗?)

问题是,在控制网站上,selectivizr.js在IE 7/8中总是正确加载。此外,在正确初始化时,CSS3 helper js和Media Query help js文件之间也没有已知的不兼容性。

我从页面中删除了selectivizr.js,在20多次刷新后页面加载的方式完全相同。好的是恢复了一致性,不好的是我失去了IE 7/8中的CSS3规则。

显然,这就是所讨论的js插件的工作原理:

根据W3C规范,Web浏览器应该丢弃它不理解的样式规则。这就产生了一个问题——我们需要访问样式表中的CSS3选择器,但IE会将它们丢弃。为了避免这个问题,每个样式表都使用XMLHttpRequest下载。这使得脚本可以绕过浏览器内部的CSS解析器,并访问原始的CSS文件。

来源:http://www.css3.info/css3-pseudo-selectors-emulation-in-internet-explorer/

如果您有任何建议的CSS3选择器插件,我可以尝试一下;也许其中一个会更可靠地加载,或者具有更少的开销,因此减少了与延迟相关的问题。还有其他替代方案吗?

或者,也许我应该在 DOM 准备好第二次(在我的脚本替换了 body 内容之后)将其添加到 head 或其他地方的 body 中。这些选项都没有起作用 - 它们的结果甚至更糟


1
使用JS来插入selectivizr.js脚本似乎会完全破坏页面。只有在<body>元素内自然解析为内容时才能正常工作。嗯。 - atwixtor

-1
首先,让我说一下我曾经参与过多个项目,其中团队已开始通过JavaScript动态生成DOM,包括通过CORS远程加载脚本。
经过数月的努力,在三个不同的项目中使用了不同的方法后,我们最终不得不面对这样一个事实:IE7和IE8无法正确或一致地动态加载和处理外部脚本或CSS。 我的建议是在PHP/服务器端合并/组合任何脚本,并提供作为一个单一文件缓存在客户端上。 另外,IE并非完全有责。下载、处理和呈现脚本/CSS的正确顺序涉及到巨大的复杂性,并编写这个过程,使其在每个环境(webkit + mozilla + IE9+)中运行良好需要接近专家级别的知识和非常彻底的测试。
在您的情况下,一个不好的"流"的例子是,当我特别查看您的页面时,它会短暂地显示未应用CSS的页面(令人不快!),然后屏幕会"更新",CSS被拉进来并应用。很糟糕。

我注意到的另一个问题是http请求数量很大。每个请求都需要进行DNS查找、缓存/过期检查(以及由头部指令决定的其他一些内容)和随后的响应下载。在桌面上,这并不明显,但在移动设备、平板电脑甚至某些较慢/卡顿的PC上尤其明显。

如果你正在当今的浏览环境下构建web应用,并且只有一个小团队,最好的方法可能是:

  1. 从CDN中提供CSS作为单个可缓存文件,并在预解析、预迭代、预呈现的HTML块中提供页面,最小化客户端JS处理(仅在加载后绑定元素),或者
  2. 使用现有的客户端框架,如Sencha、SproutCore、YUI等——它们已经为你构建了框架并修复了所有错误。

在我改变看法之前必须发生两件事:IE8必须从普通用户中消失(低于10%),并且“平均”移动设备需要拥有2个物理处理器核心。现在只有昂贵/高端型号才有双核处理器。

值得注意的是,即使使用JIT JS编译器,最快的移动处理器在JS性能方面仍然比典型桌面电脑慢10倍 - 直接与桌面电脑相比,它们将与Pentium 4或旧版AMD Athlon 64竞争。

我完全同意我应该在服务器端一次性输出所有这些样式表和脚本,但我无法这样做,因为我只是这个大型CMS平台/公司的小客户,他们不太可能允许我编辑模板或为这些节点制作特殊情况。事实上,当我发现我的限制时,我的第一个测试是一个<?PHP>命令,它只是将控制页面源代码中出现的所有内容打印出来。 - atwixtor
很遗憾,这个CMS不允许使用PHP。 - atwixtor
远程加载和执行外部脚本在IE7和8中完全正常。有很多可用的脚本加载器。你确定没有将外部脚本与跨域混淆了吗?IE7/8不支持CORS。它们有XDomainRequest,但存在许多问题。 - gregers
@gregers "工作正常"是错误的。具体情况是通过将<script>标签附加到<head>来应用脚本。在各种情况/环境中,IE7和IE8存在多个问题,无法正确工作。atwixtor可能面临的挑战是处理大量可能尝试在页面加载时执行相同/类似操作的脚本。冲突的潜力各种各样。 - Joshua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接