Simplicityを少し改造してみた 番外編 part5 スクリプトのレンダリングブロックを解消する

スクリプトごとにdefer/asyncを振り分ける記事を書きました(2016/9/3)。

wordpressで読み込まれているjavascriptにdeferもしくはasyncをつける
大体の場合、wordpressから読み込まれているスクリプトはwp_enqueue_scripts()などで読み込まれています。その際にスク...

Googleの PageSpeed insight では「スクロールせずに見えるコンテンツのレンダリングをブロックしている JavaScript/CSS を排除する」と言う部分でJavascriptとCSSがレンダリングブロックしているので何とかしなさいと言われます。

レンダリングブロックとは、こちらのページで説明されているように、

ブラウザではページをユーザーに表示する前に解析する必要があります。解析中に外部スクリプトがある場合は、解析を停止して、その JavaScript をダウンロードしなければなりません。そのたびにネットワークの往復が追加されるため、ページが最初に表示されるまでの時間が遅くなります。

このようなことなわけです。
Googleでは、ファーストビュー(スクロールしないで見える部分)に必要な小さなJavascriptや、cssをインライン化して、ページ解析をなるべく妨げないようにするか、javascriptなどは遅らせて読み込ませることで解決して下さいと書いてあります。

ここで、スクリプトを遅らせて読み込ませるのは、以下のように、asyncやdeferをスクリプトタグに挿入しておけば良いわけですが、それがWordpressになると少々厄介です。

通常のhtml5であれば、ヘッダ部分に、

と、だいぶ端折って書きましたが、こうしておけばよいわけです。

asyncは非同期に読み込みます。javascriptなどでdocument.writeを利用しているものはasyncが利用できません。そういった場合は、解析が終わった後に読み込むdeferを利用します。
asyncにしてもdeferにしても解析が終わったり読み込む準備ができたら実行するというような事なので、解析を邪魔することはありません。これがいわゆるレンダリングブロックを解消する方法の一つであるわけです。

さて、先に書いたように、Wordpressで厄介なのが、上記のようにヘッダ部分に直接スクリプトタグを書いているわけでなく、wp_enqueue_script()等で、スクリプトを読み込む順番を処理している感じです。これは例えば依存するスクリプト(jQuery等)も設定でき、そういったスクリプトはjQueryが読み込まれるまで順番待ちとなります。またヘッダで読むかフッタ前で読み込むかを設定できるためとても便利であるわけですがどうやって処理したらいいのかを理解しにくくあります。

簡単に言えば、整理券を配ってどこの列に並ぶかを制御しているスタッフがいるという感じでしょうか。jQuery依存のスクリプトはこの列、ヘッダで読む人はこの列…と言うように、htmlに出力する前に順番を整理するわけです。

例えば、自分が用意した外部スクリプトがあった時に、それがjQueryで書かれているとすると、

こんな感じでWordpressにキューを送ります。形式としては、

こんな感じとなります。詳細はcodex日本語版 | 関数リファレンス/wp enqueue script等を参考にしてください。

予めWordpressに登録されているデフォルトスクリプトもありますので、$handle部分はそれらを参考にしても良いですし、上記のwp_register_scriptのようにして、スクリプトを登録しキューを送るという準備をすればokです。

このようにして、スクリプトはWordpressに登録されてどこに挿入するのか依存関係をどうするのかをWordpressに知らせます。そして書き出すスクリプトタグは以下のようになります。

これがフッター前に挿入されるわけです。これを見てわかるように、いわゆる普通のスクリプトタグです。では、どうやってasyncやdeferを入れるのかですが、以下のようにすればできます。

スクリプトタグを修正する

これは、WordPressのscript_loader_tagを使ってscriptタグをすっきりする(YoungFlavor)からの引用です。Wordpress4.1.0から導入されたscript_loader_tagで、引用ページにも書いてありますが、「<script>タグを変更できるフィルターフック」となっています。

上記のPHPは、Simplicityの子テーマ(ない人はバックアップをとって親テーマ)のfunctions.phpに追記すればよいです。

これだけでok。ただし、上記はキューが送られてるスクリプトタグの「type=’text/javascript’」部分に全てasync属性を追加してしまいます。なので前述したように、document.writeが利用されているスクリプトも関係なくasyncが付くので問題が発生してしまいます。

そんな時は、wp_enqueue_scriptに登録された$handle部分を利用して、

こんな感じに書くこともできます。

$handleがわからない時などは、プラグインがたくさん入っていたりすると大変ですが、例えばsublimeとかのメニュー「Find」より、「Find in files(Shift+Ctrl+F)」等で検索し、一覧が表示された所で今度は通常の検索(Ctrl+F)でwp_enqueue_scriptや、該当スクリプトのアドレスやファイル名等で検索をかければハンドルが見つかると思います。

このようにして、各スクリプトに対してasyncやdeferを入れることで「非同期読み込み」あるいは「遅延読み込み」ができスクリプトによるレンダリングブロックは解消できると思います。
あくまでも、エンキューされたスクリプトに対しての方法なので、Simplicityのtext widgetに追記したものに対しては効果はありません。wp_register_scriptやwp_enqueue_scriptで外部スクリプトが登録できれば出力されるスクリプトタグは制御できそうです(jQueryのGoogle CDN等)が、レンタルサーバーの自動挿入バナー広告とかのスクリプトに関しては、また違うアイデアで処理するか、あるいは不可能かも知れません。

スポンサーリンク

シェアする

フォローする