使用requestAnimationFrame异步加载CSS样式表

时间:2015-02-08 12:48:11

标签: javascript html css pagespeed

Google建议使用以下JS代码(https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery)来优化页面速度(异步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会抛出错误&#34;对象requestAnimationFrame未定义&#34;。问题很明显,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的专家,也不是布局绘画和类似的东西,但我找不到正在发生的事情或问题所在的解释。

提前感谢任何解释或提示要寻找的内容。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我遇到了同样的问题,在我的情况下,一些移动的“用户体验”问题导致Page Speed Insights在我的异步加载的CSS开始之前分析了网站。

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

希望有更好的解决方案。