每次页面加载的时候,都会加载一系列的 css 和 js,这些资源如果加载的方式处理不当,就会造成渲染阻塞。在 Google 的排名中,网站性能被做为了很重要的一项评判指标之一,较慢的网站也会导致用户的跳出率非常高。所以,为了你网站的排名也为了更好的用户体验,优化这些资源的加载势在必行。下面会介绍在 WordPress 系统中,如何推迟这些资源的加载,加快网站的解析。


1. 延迟非必要 CSS 加载

网上有推荐使用 LoadCSS.js 库来实现 CSS 延迟加载的,但这种使用 JS 的方法有个缺点,它会造成渲染阻塞。那么,我们如何在不使用 Javascript 渲染阻塞资源的情况下加载 CSS 文件?

我们可以使用 WordPress 的函数 style_loader_tag 来实现,将下方代码添加在主题文件目录下的 functions.php 即可,根据需要修改你不想要添加延迟加载的列表名。

add_filter('style_loader_tag', function ($html, $handle, $href, $media) {
    if(!is_admin()){

        #不添加延迟加载的列表 (login.min,style...修改为你不想延迟加载的文件名)
        $styles_to_exclude = ['login.min.css', 'style.css']

        foreach($styles_to_exclude as $exclude_style){
            if(true == strpos($html, $exclude_style)) return $html;
        }
        $html = '<link rel="preload" href="' . $href . '" as="style" id="' . $handle . '" media="' . $media . '" onload="this.onload=null;this.rel=\'stylesheet\'">' . '<link rel="stylesheet" href="' . $href . '" id="' . $handle . '" media="print" onload="this.media=\'all\'">' . '<noscript>' . $html . '</noscript>';
    }
    return $html;
}, 10, 4);

使用该方法除了排除指定的样式列表外,后期即使添加新的 CSS 加载,亦不会造成渲染阻塞问题,延迟加载动作会自动作用后续添加的 CSS 文件,加载出来的结构效果如下:

<link rel="preload" href="#" as="style" id="#" media="#" onload="this.onload=null;this.rel='stylesheet'">
<link href="#" id="#" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="#" id="#" media="#"></noscript>

解析:

  • 它的工作原理: link rel="preload" as="style" 异步请求样式表,但仅支持 Chrome, Safari, Edge 等浏览器,添加第二个 <link> 是因为 Firefox 不支持 preload 属性,如果浏览器支持 preload 特性,它将只使用第一行代码,如果它不支持 “preload” 浏览器提示,那么它将获取具有 “print” 媒体属性的 CSS 文件并异步加载它。
  • 链接中的 onload 属性允许在完成加载时处理 CSS
  • noscript 标签确保如果浏览器不支持 “javascript”,它仍然可以向用户显示文件的内容,为了防止使用旧浏览器的用户看到没有实际样式的网页,使用 noscript 标签作为延迟加载 CSS 的后备很重要。

PageSpeed Insights 测试效果如下:


2. 推迟或异步加载 JS 脚本

我们可以通过为 JS 文件添加 async 或 defer 这两个属性来达到延迟加载的目的,所有现代主流浏览器包括 Chrome, Firefox 和 Edge 均已支持这两个属性。自 IE10 以来,Internet Explorer 也已经添加了对这些属性的支持。

以下是 async 和 defer 属性的作用:

  • async 属性:即异步加载脚本,浏览器在继续解析 HTML 文档的同时异步下载脚本。当脚本完成下载时,即开始执行脚本,同时阻止 HTML 解析。
  • defer 属性:即延迟加载脚本,浏览器在继续解析 HTML 文档的同时异步下载脚本。在 HTML 解析完成之前,脚本不会执行。

方式和前面延迟 JS 的方法类似,我们可以使用 WordPress 的函数 script_loader_tag 来为网站加载的一些 JS 添加相应的属性。将下方代码添加在主题文件目录下的 functions.php 即可,根据你的需要修改 defer 和 async 列表名。

// Add defer and async attributes in specify js
add_filter('script_loader_tag', function ($tag) {

    #添加 defer 属性的 js 列表,自行修改为你的 js 文件名
    $scripts_to_defer = ['search-form.js', 'comment_count.js', 'comment_embed.js'];

    #添加 async 属性的 js 列表,自行修改为你自己的 js 文件名
    $scripts_to_async = [
        'wp-embed.min.js',
        'responsive-embeds.js',
        'jquery-migrate.min',
        'single.js',
        'about.js',
        'category.js'
    ];

    foreach($scripts_to_defer as $defer_script){
        if(true == strpos($tag, $defer_script)) return str_replace(' async  async  async  async  async src', ' defer="defer"  async  async  async  async  async src', $tag);
    }

    foreach($scripts_to_async as $async_script){
        if(true == strpos($tag, $async_script)) return str_replace(' async  async  async  async  async src', ' async="async"  async  async  async  async  async src', $tag);
    }

    return $tag;
}, 10);

加载出来的结构效果如下:

<script async src="#" async="async" type="text/javascript"></script> 
<script async src="#" defer="defer" type="text/javascript"></script>

PageSpeed Insights 测试效果如下:


参考文档: