2015年に下記の記事で、Search Console(旧WebMasterTool)のPageSpeed Insightsで表示される警告「スクロールせずに見えるコンテンツのレンダリングをブロックしているJavaScript/CSSを排除する」について、当ブログで行っていた対策について書きました。
「コンテンツのレンダリングをブロックしているJavaScript/CSSを排除する」の対策をしました

もう3年経ってますし、2018年版の当ブログでの対策を書いておきます。以前はCSSの読み込みの修正が難しかったのですが、シンプルで簡単な形に修正していますよ。

PageSpeed Insightsでは、モバイル99点、パソコン92点になりました。Googleアドセンスなどの外部リソースでどうしても減点されてしまうので、100点を取るのは難しいのですが、十分満足できる点数だと思います。
PageSpeedInsightsで99点

Javascriptの対策

Javascriptについては以前の記事と同じ対策(asyncをつける、または、body部の最後で読み込む)でも良いはずですが、deferを付けるように変えています。

asyncとdeferの違いの一つに、asyncはJavascriptが実行される順序が保証されませんが、deferだと記述した順番でJavascriptが実行されるというのがあります。

したがって、JQueryを使っている場合など、先にJQueryのJavascriptをdeferで読み込んでから、次にJQueryに依存する他のJavascriptもdeferで読み込むと良いです。
<html>
<head>



//早めに読み込みたいJS(Googleアドセンスなど)
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>



</head>
<body>



コンテンツなど



<script defer src="jquery-x.y.z.min.js"></script>
<script defer src="my.js"></script>
</body>
</html>

CSSの対策

以前は下記の対策をしてました。(ファーストビュー:Webにアクセスした際にスクロールせずに見える部分のこと)
1.ファーストビューに関連するCSSをhead部でインラインで読み込む
2.ファーストビューに関連しないCSSをbody部最後に非同期で読み込む

正直、CSSをファーストビューに関連する部分と関連しない部分に分けるのは大変すぎますよね。ビジネスでWebサイトを作る場合も工数がかかってしまい、コストに跳ね返ってしまうと思います。

なので、もう面倒なので圧縮した(minifyした)CSSをすべてhead部でインラインで読み込むようにしました!自分のブログのCSSだけでなく、font-awesomeのCSSもインラインで読み込んでます(ただし、自分の場合はfont-awesomeを自分のサーバーに置いていて、font-awesomeのcssにあるwoff2などのファイルを読み込む部分はファイルパスを手修正してます)。

CSSは所詮文字なので画像などに比べたらサイズもたかが知れてますし、Webサーバー(apacheやnginxなど)による圧縮も効くはずです。

CSSを圧縮する方法ですが、私はsassを使ってCSSファイルを作っているので、sassのコマンドで–style compressedを付けて圧縮しています。

sassなんて使っていない場合は、CSSをminifyするサイト(https://cssminifier.com/など)があると思うので、そこで圧縮した内容をCSSファイルとしたり、head部に直接貼り付けてしまうといいでしょう。

<html>
<head>



<style type="text/css">
font-awesomeのCSS
</style>
<style type="text/css">
自分のCSS
</style>



</head>
<body>



コンテンツなど



</body>
</html>

WordPressでの実装

JavascriptとCSSに分けて、Wordpressでの実装について説明します。

Javascript

このブログのテーマではfunctions.phpにおいて、以下の処理を行うようにカスタマイズしています。functions.phpを下手にいじってエラーになるとWebサイトが表示されなくなったりするので、バックアップを取得するなど注意して作業してください。

1.wp_enqueue_script関数で読み込む対象のJavascriptを登録する。head部やbody部末尾にべた書きするよりもこちらの方が今風の書き方らしいです。

//管理画面でない場合(注1
if(!is_admin()) {
  //早めに読み込みたいスクリプト(例:Googleアドセンス、第5引数falseだと、head部での読み込み)
  wp_enqueue_script('adsense','//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', array(), null, false);
  //JQuery(第5引数trueだと、body部最後での読み込み)
  wp_enqueue_script('jquery3','/wp-content/themes/テーマ名/ディレクトリ/jquery-3.3.1.min.js', array(), null, true);
  //JQueryに依存するスクリプト(第3引数のarray()の中に依存するスクリプト名を書く)
  wp_enqueue_script('my-base','/wp-content/themes/テーマ名/ディレクトリ/Javascriptのファイル.min.js',   array('jquery3'), null, true);
  //その他のスクリプト(例:Twitter)
  wp_enqueue_script('twitter','https://platform.twitter.com/widgets.js', array(), null, true);
}

2.script_loader_tagにfilterを追加し、最近のブラウザでは付けないで良い「type=’text/javascript’」をasyncやdeferに置換することにより、wp_enqueue_scriptで登録したJavascriptにasyncまたはdeferを付ける。

function add_async_defer_enqueue_script( $tag, $handle ) {
  //AMPでない場合(注2
  if(!is_amp_endpoint()) {
    //asyncにしたいスクリプト
    if ($handle === 'adsense') {
      return str_replace( "type='text/javascript'", 'async', $tag );
    //deferにしたいスクリプト
    } else {
      return str_replace( "type='text/javascript'", 'defer', $tag );
    }
  //AMPの場合は何もしないでリターンする
  } else {
    return $tag;
  }
}
//管理画面でない場合(注1
if(!is_admin()) {
  add_filter( 'script_loader_tag', 'add_async_defer_enqueue_script', 10, 2 );
}

(注1)Wordpressのバージョンにより、Wordpress管理画面のウィジェットの内容を編集できなくなることがあるので、管理画面ではjavascriptの読み込みを変えないようにします(async/deferの付与が怪しそうです)。私は最初これに気づかなくて、すごく困ってました・・・。

(注2)上記では、Javascriptの読み込みにasyncやdeferを付与する処理がWordpressのAMPプラグインと相性が悪いので、is_amp_endpoint()でAMPページではないことを判定しています。AMPページを使ってない(WordpressのAMPプラグインを使ってない)場合は、以下のような関数でいいと思います(試してないので動かなかったらごめんなさい)。
/**wp_enqueue_scriptで登録したJavascriptにasyncまたはdeferを付ける*/
function add_async_defer_enqueue_script( $tag, $handle ) {
  //asyncにしたいスクリプト
  if ($handle === 'adsense') {
    return str_replace( "type='text/javascript'", 'async', $tag );
  //deferにしたいスクリプト
  } else {
    return str_replace( "type='text/javascript'", 'defer', $tag );
  }
}
add_filter( 'script_loader_tag', 'add_async_defer_enqueue_script', 10, 2 );

CSS

当ブログではfunctions.phpとheader.phpをカスタマイズし、CSSファイルまたはキャッシュ(APC)から取得した内容をhead部に出力するようにしました。

ただし、レンタルサーバーの場合はセキュリティー的に$wp_filesystem->get_contents関数で他のファイルのパスを指定して読み込めないかもしれません。その場合は、head内にべた書きしてしまうのがいいでしょう。(当ブログはレンタルサーバーではなくVPSを使っています)

functions.php
require_once(ABSPATH . 'wp-admin/includes/file.php');
/**CSSファイルのデータをAPCまたはファイルから読み込む*/
function read_css(string $apc_id, string $path, int $days) : string {
  $success = false;
  $css_data = apc_fetch($apc_id, $success);
  if ($success === false) {
    $css_data = '<style type="text/css">';
    if (WP_Filesystem() ) {
      global $wp_filesystem;
      $css_data .= $wp_filesystem->get_contents($path);
    }
    $css_data .= '</style>'.PHP_EOL;
    apc_store($apc_id, $css_data, 86400 * $days);
  }
  return $css_data;
}

header.php
<html>
<head>



<?php
echo read_css('css_font_awesome', 'wp-content/themes/テーマ/font-awesome.css', 7);
echo read_css('my-style', 'wp-content/themes/テーマ/自分のCSSファイル.css', 1);
?>



</head>
<body>


おわりに

気をつけているのですが、自分のWordpressテーマからコードをコピーしてきた際に漏れなどがあって、うまく動かない・表示されない等あれば申し訳ありません。各自の環境の違いもあって、原因を特定するのは難しいと思うので、このブログはこんな感じで対策しているんだなぁというレベルで捉えてもらえれば助かります。

近年のSEOは移り変わりが速くて大変そうですが、本件のようなWebサイトの速度については、一度修正してしまえばその後もずっと有効ですし、コンテンツみたいに基準が曖昧でよくわからないものではないので、さくっと修正しておくのも良いと思います。

何より、Webサイトの表示が速いことはユーザーにとても優しいですし、なかなか表示されなくて「戻る」や「×」ボタンを押されて離脱されるのも防げるかと思います。

私も格安SIMの節約モード(業者によって異なりますが、200kbpsぐらい)をデフォルトで使っているのですが、なかなか表示されない重いサイトも多くて、そっ閉じすることも多いです。何で2018年なのにISDN以上ADSL以下のような、約20年前の回線速度でインターネットをしないといけないんだ?という気もしますが、お金がなくて節約しないといけないから仕方ないっすね・・・。