【问题标题】:Async loading CSS stylesheet using requestAnimationFrame使用 requestAnimationFrame 异步加载 CSS 样式表
【发布时间】:2015-04-08 06:25:03
【问题描述】:

Google 建议 (https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery) 使用以下 JS 代码来优化页面速度(异步 CSS 加载)

<script>
  var cb = function() {
    var l = document.createElement('link'); l.rel = 'stylesheet';
    l.href = 'small.css';
    var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h);
  };
  var raf = requestAnimationFrame || mozRequestAnimationFrame ||
      webkitRequestAnimationFrame || msRequestAnimationFrame;
  if (raf) raf(cb);
  else window.addEventListener('load', cb);
</script>

当我使用上面的代码时,Page Speed Insights (https://developers.google.com/speed/pagespeed/insights/) 会识别它并给页面更高的分数。但问题是,这段代码在旧版 IE 中不起作用。

例如,IE 8 会抛出错误“Object requestAnimationFrame is not defined”。问题很明显,IE 8 不支持 RAF,所以会因为未定义对象而抛出错误。

我需要网站在这些旧 IE 中也能正常运行,所以我决定更新我的代码如下:

<script>
function loadCss() {
    var l = document.createElement('link');
    l.href = 'http://static.xyz.com/css/style.min.css?v=23';
    l.rel = 'stylesheet';
    l.type = 'text/css';
    l.media = 'screen';
    document.getElementsByTagName('head')[0].appendChild(l);
}

if (typeof requestAnimationFrame === 'function') {
    requestAnimationFrame(loadCss);
}
else if (typeof mozRequestAnimationFrame === 'function') {
    mozRequestAnimationFrame(loadCss);
}
else if (typeof webkitRequestAnimationFrame === 'function') {
    webkitRequestAnimationFrame(loadCss);
}
else if (typeof msRequestAnimationFrame === 'function') {
    msRequestAnimationFrame(loadCss);
}
else if (typeof window.addEventListener === 'function') {
    window.addEventListener('load', loadCss);
}
else {
    window.onload = loadCss;
}

这段代码不是很漂亮,但它在 IE7+、Firefox、Chrome 等中都能正常运行。但是当我通过 Page Speed Insights 测试它时,它无法识别 CSS 是异步加载的,也没有给我更高的分数(它显示的错误与 CSS 是通过 同步加载的一样)。

我的问题是:我的代码中是否存在我不知道的错误,或者 Google 根本无法识别这种插入异步 CSS 的方式。代码正常运行对我来说绝对重要,但我希望在 Page Speed 测试中获得更高的分数,因为这对 SEO 有好处。

我不是 Javascript 方面的专家,也不是布局绘画之类的专家,但我找不到关于发生了什么或问题出在哪里的解释。

提前感谢您提供的任何解释或提示。

【问题讨论】:

  • 你绝对需要异步加载 css 吗?
  • 不,我不知道,这不是绝对必要的。但我希望能够异步加载它,只要它可以工作并且 Google 会识别它。
  • requestAnimationFrame 被所有没有前缀的浏览器所支持,所以你并不需要 mozRequestAnimationFrame、webkitRequestAnimationFrame 和 msRequestAnimationFrame。我还觉得对于较旧的 IE 浏览器 [唯一不支持 requestAnimationFrame 的浏览器],直接 loadCSS() 而不等待 onload 可能是一个更好的主意。所以 if (typeof requestAnimationFrame === 'function') { requestAnimationFrame(loadCss); } 其他 { loadCss();}
  • @MatejHostak 我有同样的问题。你找到解决办法了吗?
  • 还没有,但如果我找到解决方案,我会发布更新。

标签: javascript html css pagespeed


【解决方案1】:

这段代码似乎对我有用(它加载异步 CSS,Google PageSpeed 接受它并且适用于旧版浏览器):

<script>
var cb = function(){
  var styles = ["http://mycdn.co.uk/stylesheet1.css", "http://mycdn.co.uk/stylesheet2.css"];
  for( var i = styles.length - 1; i >= 0; i-- )
  {
    l = document.createElement( 'link' );
    l.rel = 'stylesheet';
    l.href = styles[i];
    h = document.getElementsByTagName( 'head' )[0];
    h.insertBefore( l, h.childNodes[h.childNodes.length-1] );
  };
};

var raf = ( "undefined" != typeof requestAnimationFrame ) ? requestAnimationFrame : false ||
    ( "undefined" != typeof mozRequestAnimationFrame ) ? mozRequestAnimationFrame : false ||
    ( "undefined" != typeof webkitRequestAnimationFrame ) ? webkitRequestAnimationFrame : false ||
    ( "undefined" != typeof msRequestAnimationFrame ) ? msRequestAnimationFrame : false;

if( raf )
{
  raf( cb );
}
else
{
  if( "undefined" != typeof window.addEventListener )
    window.addEventListener( 'load', cb );
  else if( "undefined" != typeof window.attachEvent )
    window.attachEvent( 'onload', cb );
}
</script>

感谢Ultrabenosauruscode

【讨论】:

    【解决方案2】:

    您的代码异步加载 css,是的。所以很可能谷歌只是不认识你的方式。您可以尝试将 window.onload 替换为 attachEvent 以获得支持,这可能会有所帮助

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,在我的案例中,几个移动“用户体验”问题导致 Page Speed Insights 在我异步加载的 CSS 启动之前分析了网站。

      这样做很痛苦,但最终提取了解决用户体验问题的基本样式,然后将该内联的缩小版本放在标题中,同时让大部分 CSS 通过 js 异步加载。

      希望有更好的解决方案。

      【讨论】:

      • 在我的情况下,我在 head 中也有一个基本的 CSS 内联,其余的按上述插入,仍然存在这种行为,所以在我的情况下这没有帮助,但也许有一些在我的情况下其他地方出错。
      • Matej,您是否仍然收到“优化 CSS 以进行交付”消息或其他信息?因为您的代码应该已经解决了 CSS 交付问题。
      猜你喜欢
      • 2019-03-07
      • 2019-08-18
      • 2013-03-14
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 2018-04-04
      • 1970-01-01
      相关资源
      最近更新 更多