当ブログ、これまでちょこちょこと読み込み速度の改善などを行ってきたのですが、最近はずっとほったらかしにしてました。過去に改善した際は PageSpeed Insights を参考に最適化していたのですが、Google先生の評価方針も時が経って変化したこともあり、いつの間にかほとんどのページに改善が必要なひどい状態になってました。
そこで重い腰を上げて、久しぶりにブログの速度改善を行うことにしました。当ブログは通常の記事のページをはじめ、ゲーム攻略向けのWebツールを配信していたり、ゲーム情報のデータベースを視覚化したようなページがあったりしますが、今回はほとんどのページが重いと判定されているので、通常の記事の最適化を行う事にしました。具体的には以下のページを評価指標として使用しました。
まずはいつも通り、 PageSpeed Insights で速度を測ってみます。
PC版は83でまずまずなスコア。
しかし、モバイル版のスコアは悲しみの48。
メインの記事内でスクリプト等を全く使用していない通常記事でこれはまずいです。
当ブログはページの表示にPHPを使用しているため、まずはPHPの処理が重いのか、それともPHPで生成されたページ自体が重いのかを切り分けてみる事にしました。
PHPのページ生成処理をオフラインで済ませ、事前に生成したHTMLをブログにアップロードし、改めて PageSpeed Insights で評価してみました。
スコア56。これだけでも少し上がるということはPHPの処理自体もそれなりに重いようですね。
ちなみにPCの方はPHPの処理が消えてもスコア80で変化なしのようです。PHP処理はモバイル版にはやや影響するが、PC版には影響ないようです。
一応、当ブログではPHPから事前に生成したHTMLにリダイレクトする機能は実装してあるので、それを有効化すればモバイル版の速度は少し改善する事は分かりました。
ただ、オフラインでPHPを事前に生成してしまうと、記事を更新した時にHTML生成し忘れて、結局記事が更新されてなかったという事故が過去に何度かありまして、それを機にメンテナンス性を考慮し、この機能は無効化してあります。
この事故を防止できる仕組みを作るという方向性でも少しは解決しそうではありますが、それでもモバイル版のスコアが56は低いので、更にボトルネックを探ってみる事にしました。
まず、怪しいと思ったのが highlight.js です。当ブログでは技術的な記事も扱っているため、ソースコードを掲載する事も多く、highlight.js を使ってソースコードにカラースキーマを適用していました。しかし、<header>内で問答無用で読み込んで、初期化処理も行っていたため、ソースコードを扱っていない記事でも無駄に highlight.js の初期化処理が走ってしまっていました。ひとまず、highlight.js を無効化するとどうなるのか、PageSpeed Insights で調べます。
特に変わらない。highlight.js は無罪のようです。余談ですが、PHPで以下のようにする事で一応ソースコードのないページでは highlight.js の初期化処理を除外する事ができました。
$isHighliteJsEnabled = $entryId != null && $entryList->hasCodeTagInArticle($entryId);
if ($isHighliteJsEnabled)
{
// highlite.js
echo '<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css" media="print" onload="this.media=\'all\'">';
echo '<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"></script>';
echo '<script>hljs.initHighlightingOnLoad();</script>';
}
ここで $entryId は記事の表示するIDで、$entryList は記事のデータベースとなるclassです。指定したIDの記事内に<code>タグを含むかどうかを判定する hasCodeTagInArticle() という関数を実装し、その真偽値で分岐する事でソースコードを含まない記事では highlight.js の初期化は行わないようにする事ができました。
highlight.js によるスコアへの影響はなかったとは言え、仮に今後この部分を別のスクリプトに置き換えるなどして重くなった時にも関係のない記事には影響しない方がメンテナンス上都合が良いので、このようにしておくことにしました。
後はどこが重いのか心当たりがなかったので、ページ内の要素を部分的に削除しては PageSpeed Insights で評価してみる事で、重い部分を調べました。
結論から言うと、以下の2つが重かったです。
- 関連記事に表示していた記事のサムネールに表示していたYoutube動画プレビュー
- Google AdSenseの関連コンテンツ
まず、自前で実装した関連記事の表示機能なのですが、ここでは記事に含まれるメディア(画像、動画、音楽)を抜き出して、サムネールとして表示するよう実装していました。当時は画像なければ動画が出たらかっこいいよなぁとか思いながら動画をサムネールにするように実装てしまっていたのですが、普通に考えたらそりゃ重いですよね。
という事で、関連記事のサムネール生成には動画を扱わないようにしました。
続いて、Google AdSense の関連コンテンツ自体が重い方ですが、こちらは手の入れようがないので、やむを得ず無効化する事にしました。ただ、PC版の方では関連コンテンツによるスコアへの影響は低かったので、モバイル版の時だけ無効化する事にしました。
そもそも閲覧中のデバイスがモバイルかどうかって PHP でどうやって判定するの?と思って調べたところ、Mobile Detect という OSS を発見。使い方も超簡単で、Mobile_Detect.php というファイルを PHP のインクルードパスに配置して、以下のコードを実行するだけ。なんというシンプルさ。
// Include and instantiate the class.
require_once 'Mobile_Detect.php';
$detect = new Mobile_Detect;
// Any mobile device (phones or tablets).
if ( $detect->isMobile() ) {
}
これでスマホやタブレットから閲覧された時だけ関連コンテンツの表示を除外する事ができました。
この2点を改善したところ、PHP処理ありでもモバイル版のスコアがなんと95に。これには思わずにっこり。
結論としては、ほとんどのボトルネックは Google AdSense の関連コンテンツでした。
これまでもブログの最適化をしていく中で結局 Google 先生のサービスが一番重いやんけ!と突っ込んだ事は何度もありましたが、今回もやはり犯人はあなたでしたか..
Google のオススメに従ってサービスを利用していくと、Google に怒られるという理不尽さを感じずにはいられない状況になりやすいのはどうにかならないものかとは度々思いますが、まぁサイトを最適化するためにこんなに便利なサービスを用意してくれてるのは本当にありがたいので感謝すべきですね。このようにスコアとして数値が出ると、最適化をゲーム感覚で楽しみながら行う事ができるのは本当に素晴らしいと思います。