ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

WordPress, asyncとdeferでJavaScriptのロードを遅らせる。

wordpress image
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

WordPressではJavaScriptをHTMLの<script>に挿入するのにレジスタ・キューを使いますが、async, defer属性を付けるなどのカスタマイズにはちょっとした工夫が必要です。

今回は『WordPressらしい』方法で解決します。

いちばんかんたんな方法は『テンプレートに直書き』ですが、WordPressではスクリプトはレジスタとキューを使うしくみがあります。

これはインラインでも同じ。

キューに登録されたスクリプトの出力方法を変えることもできます。なぜレジスタとキューがあるのか考えてみましょう。これを使えってことです。

ということで、asyncとdeferを付けてみましょう。

asyncをつける

WPバージョン4.1以上

説明はあとにしてサンプルコードから。

function add_async() {
    if ( is_admin() ) return;

    add_action( 'script_loader_tag', function( $tag, $handle, $src ) {
        $targets = [
            // wp-includes/script-loader.php
            'wp-embed',     // wp-includes/js/wp-embed.min.js
            // my create
            'fontawesome',  // https://kit.fontawesome.com/xxxxxxxx.js
            // plugins
            // jetapack
            'mustache',     // /wp-content/js/mustache.js?ver=8.3-202015
        ];
        if ( in_array( $handle, $targets, true ) ) {
            $tag = str_replace( '<script src=', '<script async src=', $tag );
        }
        return $tag;
    }, 10, 3 );
}

'script_loader_tag' は、キューにあるスクリプトをHTML出力する直前に実行するフックです。

ここで<script>のフォーマットを変えます。

WordPressに組み込まれたものやプラグイン、自作したものでもOK。

$targetsでasyncを付けるスクリプトのハンドル・リストを作り、合致したものをstr_replaceで文字列置換します。

処理はたったこれだけ。

ちなみに、$targetsのハンドル名はWordPressやプラグインのソースをjsファイル名で検索して探しました。

(CSSはハンドル名がHTMLに出力されるが、スクリプトはそれがないのでちょっと面倒。)

WordPress.orgリファレンス

Hooks - script_loader_tag

PHP公式ドキュメント

in_array

str_replace

次はdeferを付けます。お察しの人はもう分かったでしょう。上のコードを5文字変更するだけ。

管理画面はスクリプトの量がハンパないので使いません。(エラーが出まくるのが想像できる。)

また、function名はオリジナリティが必要です。今回のサンプルはクラス内で定義したものからもってきたのでシンプルですが。(add_async())

(あと、関数をむき出しするならfunction_exists()も必要。)

deferをつける

解説はいいかなとも思いますが、一応サンプルコードだけ。

function add_defer() {
    if ( is_admin() ) return;

    add_action( 'script_loader_tag', function( $tag, $handle, $src ) {
        $targets = [
            // wp-includes/script-loader.php
            'jquery-core',   // https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
            'underscore',    // /wp-includes/js/underscore.min.js
            'backbone',      // /wp-includes/js/backbone.min.js
            'clipboard',     // /wp-includes/js/clipboard.min.js
            // themes
            'pagetop',       // /wp-content/themes/my-theme/lib/js/jquery.pagetop.js
            'origin-script', // /wp-content/themes/my-theme/js/origin.js
            'prism-script',  // /wp-content/themes/my-theme/js/prism.js
            // plugins
            // jetpack
            'postmessage',           // /wp-content/plugins/jetpack/_inc/build/postmessage.min.js
            'jetpack_resize',        // /wp-content/plugins/jetpack/_inc/build/jquery.jetpack-resize.min.js
            'jetpack-photon',        // /wp-content/plugins/jetpack/_inc/build/photon/photon.min.js
            'eu-cookie-law-script',  // /wp-content/plugins/jetpack/_inc/build/widgets/eu-cookie-law/eu-cookie-law.min.js
            'jetpack-lazy-images',   // /wp-content/plugins/jetpack/_inc/build/lazy-images/js/lazy-images.min.js
            'jetpack_likes_queuehandler', // /wp-content/plugins/jetpack/_inc/build/likes/queuehandler.min.js
            'wpcom-notes-common',         // /wp-content/mu-plugins/notes/notes-common-v2.js?ver=8.3-202015
            'wpcom-notes-admin-bar',      // /wp-content/mu-plugins/notes/admin-bar-v2.js
            'google-translate-init',      // /wp-content/plugins/jetpack/_inc/build/widgets/google-translate/google-translate.min.js
            'google-translate',           // //translate.google.com/translate_a/element.js?cb=googleTranslateElementInit
            // contact-form-7
            'contact-form-7',             // /wp-content/plugins/contact-form-7/includes/js/scripts.js
            // wordfence
            'wordfenceAJAXjs',            // /wp-content/plugins/wordfence/js/admin.ajaxWatcher.1581523568.js
            // easy fancybox
            'jquery-fancybox',            // /wp-content/plugins/easy-fancybox/js/jquery.fancybox.js
            'jquery-easing',              // /wp-content/plugins/easy-fancybox/js/jquery.easing.js
            'jquery-mousewheel',          // /wp-content/plugins/easy-fancybox/js/jquery.mousewheel.js
        ];

        if ( in_array( $handle, $targets, true ) ) {
            $tag = str_replace( '<script src=', '<script defer src=', $tag );
        }

        return $tag;
    }, 10, 3 );
}

deferをつけるスクリプトのポイントは、jQueryを使うなどロード順を守らなければいけないものを対象にします。

注意。インラインが消えないように

WordPressの公式ドキュメントもそうですが、こういう変更の仕方をよく見ます。

$tag = '<script type="text/javascript" src="' . esc_url( $src ) . '" id="dropboxjs" data-app-key="MY_APP_KEY"></script>';

これはいけません。$tagにはjsファイルのスクリプトだけでなく、インラインのスクリプトも含まれているから。

(インラインスクリプトがごっそり消える。)

script_loader_tagフックのパラメータにインラインがあればいいのですが、用意されていません。(WP5.4.1で確認。)

wp-includes/class.wp-scripts.php
/**
 * Filters the HTML script tag of an enqueued script.
 *
 * @since 4.1.0
 *
 * @param string $tag    The `<script>` tag for the enqueued script.
 * @param string $handle The script's registered handle.
 * @param string $src    The script's source URL.
 */
$tag = apply_filters( 'script_loader_tag', $tag, $handle, $src );

パラメータに追加されるのを待つのみです。

注意。動作確認をサボらない。

async, deferを付けたらスクリプトが正常に動作するのか確認しましょう。スクリプトの実行タイミングが変わるのでエラーになることがあります。

とくにjQueryまわりは注意。jQueryを使っているスクリプトはその前にjQuery本体のスクリプトがロードされている必要があります。

だからサンプルコードでも、jQueryまわりはロード順が不明なasyncではなく、ロード順を守ってくれるdeferを使っています。

それでもスクリプトエラーになることはあるので、エラーにならないことを確認しながら作業をしてください。

前の投稿
WordPress, JavaScriptとCSSをインラインで出力する
WordPress,『現在メンテナンス中のため、しばらくの間ご利用いただけません。』の手動解除
次の投稿

WordPressの本

post-cta-image

たくさんあるなかで、WordPressの基本が学べる、目的別に学べる本を選びました。

  • WordPressの基本。
  • Webサイト作成から運用まで全体的に学ぶ。
  • かんたんなカスタマイズを学ぶ。
  • 何も分からないところから学ぶ。
  • WordPressからPHPプログラミングを学ぶ。

の5冊です。どうしてもネット上で調べて勉強するのが苦手という人におすすめです。

この内容をモノにすればほかの本は必要ありません。あとは自分の力で、書籍を使わずにインターネット上にある情報だけで学んでいけます。

コメントを残す

*