【WordPress】レンダリングをブロックするJavascriptやCSSの読み込みを遅らせる②

レンダリングブロックの対策

現在はプラグイン「LiteSpeed Cache」を使用していますが、以前はこんな方法でレンダリングをブロックする Javascript や CSS の読み込みを送らせていました。

rel="preload" で先読みする方法や async・defer 属性を付加する方法(.js)と、function.php でフックを使い </body> の手前に移動させる方法があります。

長くなったので分けました。
function.php で Javascript や CSS をフッターへ移動させる方法はこちらへどうぞ。

preload で先読みする

この方法にはこんなデメリットがあります。

デメリット
  • IEなど一部のブラウザでは対応されていない
  • テーマのファイルを編集する必要がある

2018年11月現在の各ブラウザの対応状況はこんな感じです。

preload対応状況

出典元:Can I use

実装する方法

<head> 内で html の読み込みやレンダリングと並行して CSS・JS ファイルを読み込んでおき、任意の場所で実行させます。

preload に対応していないブラウザでは普通に CSS や JS を読み込む場合

テーマの header.php などを開いて、元々 CSS・JS が読み込まれている部分より前(なるべく最初の方)に、2・3行目のコードを書き足します。
2・3行目を記述した位置で読み込みが始まりますが、実際にこれらのファイルが実行されるのは 5・9行目にあたる部分です。必要であれば好きな位置に移動させてください。

html

<head>
  <link rel="preload" href="先読みしたいCSSのURL" as="style">
  <link rel="preload" href="先読みしたいJSのURL" as="script">
  メタ情報など
  <link rel="stylesheet" href="先読みしたCSSのURL">
</head>
<body>
  サイトコンテンツ
  <script src="先読みしたJSのURL"></script>
</body>
参考 rel="preload" によるコンテンツの先読み MDN

現在は違いますが、以前はこの方法で GoogleFonts の読み込みを行っていました。
SANGO で Google Fonts の遅延読み込みを行う方法については、また別記事にまとめたいと思います。

全てのブラウザに対応したい場合(CSSのみ)

全てのブラウザに対応させるには、Filament Group, Inc. が提供している loadCSS というライブラリを使います。

html

<link rel="preload" as="style" href="読み込むCSSのURL" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="読み込むCSSのURL"></noscript>
<script>
/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
ここにcssrelpreload.jsの中身を貼り付けます
</script>

loadCSS rel=preload polyfill script(cssrelpreload.js)
リンク先のコードを5行目の位置に貼り付けてください。

参考 loadCSS: A function for loading CSS asynchronouslyGitHub - filamentgroup

注意点

style.css などメインの CSS ファイルをこれらの方法で非同期読み込みさせると、スタイルが適用されないままのページが一瞬表示されてしまうことがあります。
これを避けるため、ファーストビューに必要な CSS を <head> 内にインラインで記述しておくことをおすすめします。

注意

SANGO のように function.php などでCSSやJSの読み込みを制御しているテーマの場合、関数ファイルの修正や出力をキャンセルする処理が必要になります。
上記をそのまま header.php などに追記すると二重読み込みが発生しますのでご注意ください。

async・defer 属性を付加して非同期で読み込ませる(JSのみ)

Javascript の場合は、<script> に「async」「defer」という属性をつけることで、JS ファイルの読み込み・実行を非同期で行うことができます。

実装する方法

非同期で読み込みたいJSを呼び出している<script>に、acync または defer の属性を付けるだけです。

html

<script src="読み込むJSのURL" async>
<script src="読み込むJSのURL" defer>

acync と defer の違い

これらの属性を持たないデフォルトの状態では、ページの読み込みが <script> に達した時点で一旦 html の読み込みが止まり、JS ファイルがダウンロードされて実行されます。
これが PageSpeed Insights などでよく指摘される「レンダリングがブロックされる」という状況です。

<script> に acync や defer を付けると、<script> の部分で html の読み込みは止まらず、並行して JS ファイルのダウンロードが始まります。ここまでは両属性とも同じです。

実行のタイミング

acync と defer の違いは2つ。まず1つ目は、ダウンロードされた JS ファイルが実行されるタイミングです。

async を付けた場合は、JS ファイルのダウンロードが終わり次第、html の読み込みを止めて JS ファイルを実行します。
defer の場合は、JS ファイルのダウンロードが終わっても待機し、html の読み込みが終わった時点で JS ファイルが実行されます。

実行される順番

もう1つの違いは、複数の JS ファイルに同じ属性が付加されている場合の実行順です。

まず async の付いたものが複数ある時ですが、JS ファイルの読み込みが終わったものから実行されていくため、記述した順番と実行される順番が変わってしまうことがあります。
defer の方は html の読み込みが終わった時点で実行されるので、記述した通りの順番で実行されます。

使い分けが必要な例と注意点

例えば jQuery のライブラリをこの方法で非同期読み込みさせる場合、jQuery を利用して処理を行う別の JS ファイルよりも先に読み込む必要があります。
acync で読み込みの順番が変わり、jQuery の読み込みが後になってしまうと後者は動かないので、defer を指定しなくてはいけません。

また、<head> や <body> 内にインラインで jQuery のライブラリを利用する処理が書かれていた時や、jQuery を利用するプラグインが先に読み込まれる時なども同様です。
この場合はその処理やプラグインの部分よりも前に jQuery の読み込みが終わっている必要があるため、非同期で読み込むことはできません。