OSSANS Project since 2020

「もし四十のおっさんがプログラミングを始めたらどう人生変わるのか」
このブログのメインテーマです
肩肘張らずにユルく、ときたま厳しくやっていきます
※プログラミング以外のことも書きます

WordPress

2022.09.01(更新)

ページロード遅延が改善 !レンダリングブロックを防ぐ方法【WordPress / JavaScript編】

アイキャッチ画像
WordPress

WordPressでJavaScriptファイルを非同期で読み込みたいんだけど、どうやったらいいの?

こんなお悩みに答えていきます。

本記事の内容

  • レンダリングブロックの仕組み
  • スクリプト処理の流れ
  • JavaScriptファイルを非同期で読み込む具体的な方法

本記事を対象とする方

  • フロントエンドエンジニアを目指す方
  • Webディレクターを目指す方
  • SEO施策担当者

この記事を書いている僕はプログラミング歴2年です。webエンジニアとして”社内転職”しました。

レンダリングブロックの仕組み

こちらの記事にも書いたのですが、おさらいの意味をこめて解説します。

ブラウザがWebページにアクセスすると、htmlファイルのソースを上から順番に読み込んでいきます。

読み進めながらDOMツリー構築を行い、ブラウザにその結果を表示することレンダリングと言います。

<head>タグ内には様々なサブリソースファイルがあり、ブラウザはサブリソースファイルを見つける度に読み込みを一旦ストップし、ファイルをダウンロードして、そのファイルのソースを実行し、それが終了した後に読み込みを再開します。

レンダリングブロック ※一旦読み込みがストップします

これがレンダリングブロックの仕組みです。

当然ながら、JavaScriptファイルのスクリプト処理もレンダリングブロックの対象になります。

ただし、CSSファイルと違ってスタイリングを行うものではないので、JavaScriptファイルは基本<body>タグが閉じる直前で読み込みます。

Check

余談ですが、CSSファイルも<body>タグ直前で読み込み可能です。

しかしその場合、DOM構築後にスタイルが適用されるので、レイアウトが崩れたデザインが先に表示されます。これをFOUC=Flash Of Unstyled Content と言います。

<head>タグ内にあるCSSファイルを非同期で読み込んだ場合も、このFOUCが起こります。

スクリプト処理の流れ

ブラウザがJavaScriptファイルを読み込んでから処理をするには以下の3つの流れがあります。

スクリプト処理の画像 ※通常、async、deferの3通りがある

通常、ブラウザがスクリプト処理を読み込む場合、そのリソースファイルをダウンロードし、スクリプト処理を行う間、DOM構築処理をブロックします

しかし、<script>要素にasyncもしくはdefer属性を与えると、その要素のダウンロードは非同期で行われ、DOM構築処理をブロックしません

asyncは、「asynchronous」の略語で「非同期の」という意味です。deferは、略語ではなく「延期する」という意味があります。

プログラムにおけるasyncとdefer属性の違いですが、asyncの場合、ファイルのダウンロードが完了するとスクリプト処理まで行います

一方deferの場合、ファイルがダウンロードされてもスクリプト処理は行わず、DOM構築処理を優先します。スクリプト処理はDOM構築完了後になります。

よって、asyncは少なからずページロードに影響を与えます。

CSSもJavaScriptも同じですが、ページのメインコンテンツ表示に関わる重要なソースはインラインで<head>タグに読み込ませ、それ以外の優先度の低い処理は、タグの閉じる直前で非同期で読み込ませるのが、DOM構築に影響を与えない方法となります。

JavaScriptファイルを非同期で読み込む具体的な方法

ではJSファイルを非同期で読み込みましょう。それにはフィルターフックという機能を使います。

先程説明したように、<script>要素にasyncもしくはdefer属性を付けます。

両者には違いがあるので、スクリプト処理の内容によってどちらかを選択するべきですが、ページのメインコンテンツの表示をインライン形式で記述しているのであれば、それ以外のスクリプト処理の実行はDOM構築完了後でも十分でしょう。それを前提としてこの例ではdefer属性を選択するものとします。

今回はWordPress編ですから、functions.phpに以下のコードを追加します。

  1. function scriptLoaderJs($tag, $handle, $src) {
  2.   if (is_admin()) {
  3.     return $tag;
  4.   }
  5.   $tag = sprintf('<script src="%s" type="text/javascript" async=""></script>' . "\n", $src);  
  6.   return $tag;
  7. }
  8. add_filter('script_loader_tag', 'scriptLoaderJs', 10, 3);

※コードを実行する際は必ずバックアップを取ってください。予期せぬエラーが起こっても責任を負えません。

フィルターフックのscript_loader_tagを使います。ファイルターフックとは、WordPress上の何らかの出力や処理(関数実行)をカスタマイズする機能です。これにより、デフォルトで設定されている内容を上書きすることができます。

ファイルターフックは様々なものが用意されているので、興味のある方はWordPress Codexをご覧ください。

では順番に説明していきます。

まずは関数を登録します。名前はなんでも良いですが、今回はscriptLoaderJsとしておきます。この関数は$tag,$handle,$srcの3つパラメーターを取ります。

  1. function scriptLoaderJs($tag, $handle, $src)  
$tag: 通常出力される<script>タグ
$handle: wp_enqueue_styleで登録したハンドル
$href: サブリソースファイルにアクセスするURL

WordPressの管理画面ページではレンダリングブロックをする必要がないので、フックをかけず通常の<script>タグを出力させます。

  1.  if (is_admin()) {
  2.     // 管理画面ページでは非同期読み込みを適用しない
  3.     return $tag;
  4.  }

ここからがカスタマイズする内容、つまりasyncもしくはdefer属性を付与するコードです。

  1. $tag = sprintf('<script src="%s" type="text/javascript" defer=""></script>' . "\n", $src);  
  2.   return $tag;

asyncを付けたい場合は、defer=””の部分をasync=””に修正すれば変更できます。

returnしているsprintf()は、PHPの組み込み関数で、フォーマット化された文字列を返すことができます。

詳細はPHPマニュアルで確認できるので興味のある方は確認してみてください。

最後にフィルターフックの関数を実行して終了です。

  1. add_filter('script_loader_tag', 'scriptLoaderJs’, 10, 3);  

1番目のパラメーターは、WordPressの組み込み関数である’script_loader_tag’が入ります。

2番目のパラメーターは、定義したメソッド’styleLoaderJs’を入れます。これはコールバック関数と呼ばれています。

3番目のパラメーターには10が入っていますが、これは同一フックに複数の関数が登録された時に呼び出される優先順位で数字が低いほど先に呼ばれます。デフォルト値は10です。

4番目のパラメーターは、コールバック関数に指定した引数の数が入ります。今回は$tag, $handle, $srcの3つを設定しているので3となっています。

では、chromeのDevToolsを開いてソースを確認してみましょう。

defer設定前の画像 ※defer設定前のソースコードです
defer設定後の画像 ※defer設定後のソースコードです

しっかりdefer属性が付与されています。この結果、サードパーティー(プラグイン)製含め、そのテーマで読み込んでいる全てのJavaScriptファイルにdefer属性が付くことになります。

deferが機能しているかどうかはPageSpeed Insightで、”レンダリングを妨げるリソースの除外”の項目を確認するのが良いでしょう。

pagespeedinsightsの画像 ※deferが設定されたCSSファイルはこの項目に入っていないはずです

今回のまとめ

今回はJavaScriptファイルのレンダリングブロックを防ぐ方法について紹介しました。細かく突き詰めていくと、ページ毎に読み込むJSファイルを限定する処置をしないと、無駄にリソースファイルを実行することになるので、時間がある時にそうしたこともやっておくと良いでしょう。最後まで読んで頂きありがとうございました。

functions.phpにフィルターフック’script_loader_tag’を設定する

PHP組み込み関数のsprintf()を使い、設定したい文字列をフォーマット形式にする

defer設定後は、PageSpeed Insightsで結果を確認する

関連記事

  • WordPress
    ブログアイキャッチ画像
    WordPress
    2022.10.26(更新)

    【コピペ可】WordPressサイトをPWA化するためにService Workerを実装してみた。

  • WordPress
    ブログアイキャッチ画像
    WordPress
    2022.09.01(更新)

    【プラグインなし】WordPressで制作したサイトをPWA化してみた話。

  • WordPress
    ブログアイキャッチ画像
    WordPress
    2022.09.01(更新)

    ページロード遅延が改善 !レンダリングブロックを防ぐ方法【WordPress / CSS編】

CATEGORY カテゴリー別最新記事

  • CSS
    アイキャッチ画像
    CSS

    【CSS】margin?position?要素の中央寄せで使うプロパティとは?

  • Docker
    アイキャッチ画像
    Docker
    2022.10.03(更新)

    【簡単設定!】DockerでWordPressをローカル開発する方法

  • HTML
    アイキャッチ画像
    HTML
    2023.02.18(更新)

    【図解あり】aタグの入れ子ルールとHTMLの入れ子ルールを覚える方法

  • JavaScript
    アイキャッチ画像
    JavaScript
    2023.03.04(更新)

    【実例コードあり】覚えておきたいパララックスデザインの3つの基本

  • Python
    アイキャッチ画像
    Python
    2023.02.09(更新)

    【やらなきゃ損!】2日でできるPythonのExcelコピペ自動化!

  • Study
    アイキャッチ画像
    Study
    2023.02.16(更新)

    稼ぐために始めたプログラミングのこれまでの振り返り。勉強方法や役立った本も紹介。

  • web site
    アイキャッチ画像
    web site
    2022.11.26(更新)

    ページ表示速度アップ!npmでソースファイルを軽量化する方法【サクッと簡単!】

  • WordPress
    アイキャッチ画像
    WordPress
    2022.10.26(更新)

    【コピペ可】WordPressサイトをPWA化するためにService Workerを実装してみた。