[WordPress] <script>タグに defer/async を付与する方法

functions.phpにコードを追加して<script>タグにdefer/async属性を付与する。

defer/asyncとは

async属性

ダウンロード完了直後、レンダリングとスクリプトを平行して実行する。

defer属性

ページの解析後、レンダリングとスクリプトを平行して実行する。
ただし、スクリプトはレンダリング完了後に実行する。

注意

実行順序が保障されなくなるため、ライブラリなどにasync・deferは指定しない方がよい。
また、document.write()などのレンダリング関連の処理があると使えない。


functions.php に追加するコード

clean_url

function add_attr_for_script($url) {
  return ( strpos($url, '.js' ) === false ) ? $url : $url ."' defer='defer' async='async";
}
add_filter('clean_url', 'add_attr_for_script', 11, 1);

一括で付与するので用法を守って正しくお使いください。


ライブラリを読み込んでる場合はこういう条件も入れた方がいいかも

if ( strstr($url, 'jquery') !== false ) {}

script_loader_tag

大抵の場合、以下の様な形でスクリプトを出力用のキューに入れて出力していると思う。

wp_enqueue_script('js', get_template_directory_uri(). "hoge.js", [], null, true);

ここでは、スクリプトのハンドル名を指定を「js」としているが任意で付けて良い。この名称を後述の処理で使用する。

function add_async_to_script( $tag, $handle ) {
     if ( 'js' !== $handle ) { // wp_enqueue_scriptに指定したハンドル名'js'
          return $tag;
     }
     return str_replace( ' src', ' async="async" src', $tag );
}
add_filter( 'script_loader_tag', 'add_async_to_script', 10, 2 );

ifの条件は!==でも===でもどちらでも良いが、やっている事はclean_urlと大差ない。