根据 Google 优化 CSS 交付

Optimising CSS delivery according to Google

所以我 运行 通过 Google 的 PageSpeed Insights 我的站点,它告诉我可以通过延迟加载非关键资源来改进 CSS 交付。特别是它提到了字体 awesome:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

我想我可以通过简单地将它放在结束 body 标记之前的脚本之前来延迟它的加载,如下所示:

  ...
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
  <script src="js/min/scripts.min.js"></script>
</body>
</html>

但是!在查看 Google 的 documentation on delivery speed 时,我发现了两种不同的解决方案。

以我的母语(荷兰语;您可以在右下角更改文档的语言)文档说明我应该将非必要的 css 放在下面 结束 html 标签。这对我来说似乎非常奇怪。 尝试通过 JS 访问文件时,这不会使事情复杂化吗? 为什么不将它放在结束 body 标记之前?

  ...
  </body>
</html>
<link rel="stylesheet" href="small.css">

然而,在英文文档中,事情变得更加复杂,需要 JavaScript:

    ...
    <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>
  </body>
</html>

为什么需要 JS? 是不是有点过头了?

我的方法有什么问题?为什么不能在结束正文标记之前加载非关键 CSS?

我建议您查看此存储库:https://github.com/filamentgroup/loadCSS

LoadCSS 是 Filament Group 的人员编写的一个非常精明的脚本,用于以某种方式延迟加载样式表,大多数浏览器都能很好地配合使用。 如果 Javascript 被禁用或出于任何原因脚本将无法运行,则也包含回退。

我认为您关注的是他们(令人困惑的)文档的错误部分。我认为他们真正想要分享的是,您应该将您的关键 CSS 内嵌到您的 html 中。看style标签里的蓝色class

<html>
  <head>
    <style>
       <!-- This is what they are trying to show -->
      .blue{color:blue;}
    </style>
    </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
    <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>
  </body>
</html>

我阅读了相同的法语文档,它似乎和您的荷兰语版本一样过时,他们再次将蓝色 class 内联

<html>
  <head>
    <style>
      .blue{color:blue;}
    </style>
    </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
  </body>
</html>
<link rel="stylesheet" href="small.css">

他们想说的是,关键 CSS 可以直接放入 html 而无需加载整个 CSS 文件。在他们的示例中,蓝色 class 很关键,因为它是唯一使用的。

关于html标签的外部,它确实是无效的HTML,但浏览器似乎还是允许的。对于 JS 代码部分,我猜他们正试图在 header 中添加样式表,但只有在 JS 将被执行时,这意味着在页面加载结束时。此时,您可能需要考虑代码的可读性而不是性能。

外部样式表将阻止页面呈现,直到它完全加载。 Google 建议将文档最初可见(关键,首屏)部分所需的样式放在头部的 <style> 标签内(您唯一可以放置的地方可以定义非内联样式) 来避免这种渲染阻塞。非关键样式(当您登陆页面时不会直接看到的样式)作为外部样式表添加到头部 after HTML 已被读取。这样它会首先呈现,然后才会加载所有其他样式。这一切都是为了尽快向访问者展示内容,而不是让 her/him 等待不必要的时间。

它认为在大多数情况下 超过了 Google 推荐的内容,他们只是在几毫秒内变得异常 - 他们的方法才有意义如果 CSS 很大。但我认为很难,如果不是几乎不可能的话,用当前可用的工具进行维护。例如,如果它是一个回访者,他在较早的时候向下滚动了页面并会自动再次登陆那里(Opera 是一个对此非常顽固的浏览器)?仅此一项,您就需要更多的 JS,并且可能需要处理样式。那不是一个好方法。即使是初始显示,您也必须直接在头部填充一些媒体查询,以便在不诉诸全屏部分的情况下尝试正确处理。这一切都适得其反,而且过于复杂。

<style><link> 标记放在头部部分之外可能有效,但这是不正确的。我确信 Google 不再站在那个立场上,而且英文版是唯一有效的文档。 编辑 - 请参阅评论了解其中的细微差别。

即使有人按照 google 的方式进行操作并在 PageSpeed Insights 上获得 'good' 分数也没有太大意义。您仍然可以隐藏整个页面,并且仅在 所有内容 已加载(这并不罕见)时才显示它,而不会影响分数。

我个人决定忽略它,直到他们实现了一个你可以异步加载 CSS 的功能(就像你已经可以使用 JavaScript 和 async 一样)就像是在文档中宣布。它仍然需要一个特殊的用例,但至少你可以为它构建一个框架。我自己不喜欢插件。

Google 文档中缺少一件重要的事情 - 在禁用 JavaScript 时提供回退。幸运的是 HTML5,<noscript> 标签可用于此:

<head>

/* other stuff */

<noscript><link rel="stylesheet" href="small.css"></noscript>
</head>

旁注 - Google 自己的分析脚本将阻止完美的 PageSpeed 得分,因为他们在其上设置了(逻辑上)快速缓存过期。图那个。

回答您的具体问题:

  1. Javascript 不需要完成你想要的。有几种以非阻塞方式加载 CSS 的方法。有些依赖 JS,有些则不。 Filamant 集团 LoadCSS is a JS option. Critical Path's CSS Generator is one non-JS method. The process of generating the critical CSS can also be automated using Gulp or Grunt.

  2. 虽然您的方法可行,但不推荐。 Google 建议使用 Javascript 加载非关键 CSS 文件,以便在页面加载完成后将 CSS 加载到 head

备选方案

有两种方法可以改进您当前的实施。

  1. 听起来您当前正在加载 2 个 CSS 文件 - 您网站的 CSS 和 font-awesome.min.css。这需要 2 个 HTTP 请求并且会导致一个小的延迟。将 2 个文件中的 CSS 合并为一个 CSS 文件。

  2. 正如其他人指出的那样 Google 建议将关键的 CSS 内联到页面的 head 中,并加载剩余的 CSS以非阻塞的方式。我发现另一个有用的选项是将 CSS 的 全部 内容加载到 style 标记内的站点 head 中。如果您的 CSS 文件相对较小且已最小化,我建议

 <head>
   <style>
     // ALL YOUR CSS
   </style>
 </head>

嗯,有 3 个主要部分,您可以在其中放置

第一个是 body,第二个是 head,第三个在 html 中无处不在,尝试使用它