ちょっと久々にWordPressネタ。
今回はwp_head()関数とwp_footer()関数から出力されるscript要素を非同期化しようじゃないかというお話です。

いわゆるレンダリングブロックの原因になるjavascriptの読み込みを遅延させて体感速度を上げていきます。

code.close()code.close() Photo by ruiwen

async属性を使おう

async属性をざっくり説明すると、script要素に指定することで実効タイミングを指定することができる論理属性です。
asyncを付与すると、利用可能になった時点でスクリプトを実行します。

<script src="/js/script.js" async></script>

記述としては上の通り。
javascriptの実行時にレンダリングブロックせず、非同期で実行されます。

WordPressでasync属性を使う

そんなasync属性をWordPressで使うには、ちょっとゴニョっといじらないといけません。このゴニョっといじるのがイヤだという人は、同種の働きをしてくれるプラグインを使えばいいと思います。

思いますが、プラグインによっては思い通りの実行ができなかったり、依存関係にあるスクリプト全てにasyncが付与されて動かなくなったりするケースもあるので、個人的にはプラグインレスがオススメ。

functions.phpの中にadd_filter()関数を使ってゴニョります。

if (!(is_admin() )) {
function add_async_to_enqueue_script( $url ) {
    if ( FALSE === strpos( $url, '.js' ) ) return $url;
    if ( strpos( $url, 'jquery.min.js' ) ) return $url;
    return "$url' async charset='UTF-8";
}
add_filter( 'clean_url', 'add_async_to_enqueue_script', 11, 1 );
}

基本、これをまるっとコピペしてしまえばいいだけです。

if ( strpos( $url, 'jquery.min.js' ) ) return $url;の部分はasyncを付与しないスクリプトを指定しています。
上記をコピペしてみて、スクリプトの実行がおかしい、あるいは実行されないという状態になった場合は、原因と思われるスクリプトを指定して除外するようにしてください。

大概は問題ないかと思いますが、Syntaxhighlighter系のプラグインが引っかかるかもしれませんね。まぁ自分のサイトに応じて変えてくださいませ。

async属性ではなくdefer属性にする

非同期化するにあたって、async属性ではなくdefer属性を利用したいというケースがあるかもしれません。

defer属性はHTMLの読み込みが完了、正確にはDOMContentLoaderイベントの前に、スクリプトを実行するよう指定する属性です。

if (!(is_admin() )) {
function add_defer_to_enqueue_script( $url ) {
    if ( FALSE === strpos( $url, '.js' ) ) return $url;
    if ( strpos( $url, 'jquery.min.js' ) ) return $url;
    return "$url' defer charset='UTF-8";
}
add_filter( 'clean_url', 'add_defer_to_enqueue_script', 11, 1 );
}

asyncdeferに書き換えただけですが、defer属性を利用したいという場合は、こちらをペロッとコピペしてください。

当ブログではasync属性を付与するようにしましたが、やっぱり体感的な速度は上ったかなぁという印象。
まぁ、そもそもサーバーの応答速度が遅いので、本気で改善するならサーバーを乗り換えるべきなんですけどね。。

Commentsコメントしてもらえると励みになります

  • yokudekiru

    clean_urlはワードプレスで非推奨タグになったみたいです。
    かわりに、esc_url()を使ったほうが良いかもしれません。

    あとasyncは正確に文法上正確に書くととasync=”async
    deferはdefer=”defer”の方が良いみたいです。

    • この記事で出てくるclean_urlは関数ではなくフィルターフックなので、別に問題ありません。
      また、async/defer属性ですが、HTML5の各種ドキュメントを見ればわかりますが、省略可能である仕様となっているので、こちらも問題はありません。

      • yokudekiru

        >clean_urlは関数ではなくフィルターフック
        そうなんですね!初めて知りました。ありがとうございます。

        >省略可能
        http://www.tagindex.com/html5/page/script_method.html
        本当ですね!async/deferって省略可能なんですね。

        いろいろ勉強できました。ありがとうございました。