WordPress

WordPress优化CSS和JS的加载(2021)

通常情况下,css和js会阻碍html的解析,在谷歌测速里会被当成阻碍渲染的资源。如何优化呢?答案很简单,给javascript文件添加defer标签,异步加载。css文件,可以用preload方式加载,也可以用一点小技巧使其异步加载。本文简单介绍如何优化CSS和JS的加载。

根据$handle选择异步加载的脚本

function sola_defer_scripts($tag, $handle, $src) {

    $defer = array(
        'hoverintent-js',
    );
    
    if (in_array($handle, $defer)) {
        return '<script src="'.$src.
        '" defer="defer" type="text/javascript"></script>'.
        "\n";
    }

    return $tag;
}
add_filter('script_loader_tag', 'sola_defer_scripts', 10, 3);

根据文件的url选择异步加载的脚本

这段代码把除了jquery之外的脚本都defer掉。

function sola_defer_scripts( $tag, $handle, $src ) {

    // Do not defer jquery
    if ( strpos( $src, 'jquery.min.js' ) ){
       return $tag;
    }

    // Defer everything else
    return str_replace( ' src', ' defer src', $tag );
}
add_filter( 'script_loader_tag', 'sola_defer_scripts', 10, 3 );

为什么defer js文件后网站报JavaScript错误

情况一:jQuery没有defer,其它脚本defer,网站报错。

一种概率比较大的可能是:并非所有脚本都被defer了。理论上jQuery正常加载,其它依赖或不依赖jQuery的脚本defer加载,defer之前不报错,defer之后也不该报错。意外情况是有些依赖jQuery的脚本没defer,那当然会出错。

什么情况下会出现部分defer? sola在使用Siteground Optimizer时发现了这种情况。使用优化插件的defer功能时,要自己检查所有带有src的script标签是否都有defer属性。

情况二:包括jQuery在内的所有脚本都defer。

jQuery也不是不能defer,你要确保所有调用jQuery的脚本都defer加载,并且inline JavaScript不直接调用jQuery

如果你在inline JavaScript中直接写了jQuery代码,而jQuery 是defer加载,就会报错。因为inline JavaScript默认不能defer,那jQuery还没加载它就运行了,肯定不行的。一种解决方案是将jQuery Ready事件放到DOMContentLoaded事件上执行。

<script>
  window.addEventListener('DOMContentLoaded', function(){
    if ( typeof(jQuery) !== 'undefined' ){
      jQuery(document).ready(function($) {
        // Your jQuery code
      });
    }
  });
</script>

关于这个问题更详细的讨论,请参考How to defer inline Javascript?

Preload或者异步加载CSS

CSS preload会让浏览器以最高优先级下载文件,并且不再阻碍html解析。下面的代码演示了两种异步加载css的方法,一种是Scott Jehl在文章The Simplest Way to Load CSS Asynchronously介绍的方法,另一种是css preload,根据自己的需要选择即可。

function sola_defer_styles( $tag, $handle, $href, $media ){

  $not_to_defer = array(
    'theme-main',
  );

  if ( ! in_array( $handle, $not_to_defer ) ) {

    return '<link rel="stylesheet" href="' . $href . '" media="print" onload="this.media=\'all\'">' . "\n" .
    '<noscript><link rel="stylesheet" href="' . $href . '" media="all"></noscript>' . "\n";

  } else {

    // Preload css
    $tag .= '<link rel="preload" href="' .$href. '" as="style">';
    
  }

  return $tag;
}
add_filter( 'style_loader_tag', 'sola_defer_styles',10, 4);

Inline CSS

渲染页面顶部的样式或者只用在某些页面的样式可以内联加载,可以用wp_head hook或wp_print_styles hook来打印样式。使用时要注意优先级,如下所示。

add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
add_action( 'wp_head', 'wp_print_styles', 8 );
add_action( 'wp_head', 'wp_print_head_scripts', 9 );

还有一个函数叫wp_add_inline_style(),通常它要和一个样式表关联,但也可以仅用来输出内联样式,方法如下:

add_action( 'wp_enqueue_scripts', 'sola_inline_styles' );
function sola_inline_styles(){
  $styles = 'body{background:#000}';
  $handle = 'my-custom-style';
  wp_register_style( $handle, false );
  wp_add_inline_style( $handle, $styles );
  wp_enqueue_style( $handle );

}

如何查看网站加载了哪些脚本

Sola喜欢用Query Monitor插件查看,也可以用代码,点击参考文章里的链接就有。

参考文章:

留言

您的电子邮箱地址不会被公开。 必填项已用*标注