これはCAMPHOR- Advent Calendar 2019の5日目の記事です。
ずっと自分のブログの表示速度が遅くてエンジニアの端くれとして情けないなぁと感じていたので、本気でパフォーマンス改善をしてみました。やった施策を時系列順にまとめてみました。いろいろやりすぎてかなりの長文になってしまったので時間のない人は目次から飛んで気になる施策とその効果だけ読んでください。笑
また、このパフォーマンス改善をやるに当たって、以下の有名な本読んでみました。かなり参考になったのでまだ読んだことのない人はこの機会にぜひ!
評価方法
測定条件
"推測するな。測定せよ。" という有名な言葉に従って定量的にパフォーマンスを評価していくことにしました。ただ、完璧に同じ条件では測定できないので、±3点ぐらいは誤差の範囲とみなしています。
今回は以下の条件で測定することにしました。

モバイルをターゲットとし、低速な4G回線(約 1 Mbps)を仮想的に再現した状況下でパフォーマンスを評価していきます。この条件を採用した理由としては、これをGoogleが推奨しているからです。
また記事としては画像・リンク・文章量が多かったTreasureに参加したときのブログを測定用の記事として選びました。
平成最後の夏を最高のメンバーと共に最高にエモいインターンに参加してきました。 ====2018.9.21 他の参加者のブログへのリンクを追加しました!===== ====2018.9.16 他の参加者のブログへのリンクを貼りました!==[…]
現状
この条件下でまずは測定を行ってみました。
恥ずかしながらかなりスコアが悪いですね。。笑
裏を返せば結果が出しやすいということで頑張れそうです!
スクショを撮り忘れたのですが、この時点でのボトルネックとしては、
- 画像サイズが大きすぎる
- レンダリングをブロックしているCSS/JavaScript
の2つが主に問題になっていました。サーバーのスペックが低い(月250円のレンタルサーバーw)のでサーバーのレスポンスがボトルネックになっているのかと思っていたのですが、案外そうでもありませんでした。ただし、レンダリングをブロックしてる要素に関してはサーバーにアクセスするのであながち間違ってはいないと考えられます。
KPI
以上を踏まえて、パフォーマンス改善のKPIを設定していきます。
今回は、Speed IndexをKPIとします。最初はTTI(Time to Interactive)をKPIにしていたのですが、広告の取得やレンダリングがあり自力で解決仕切れない問題まで含んでいることがやっている途中でわかったので、Speed IndexをKPIにすることにしました。
このKPIであるSpeed Indexを 2.0 s 以下にすることを目標としてパフォーマンス改善をすることにしました。3.5 s 以下であれば緑色になって合格なのですが、広告に時間がかかることも考えて厳しいめの 2.0 s 以下を目標にしています。
各メトリクスに関しては以下の記事が参考になります。
色々なパフォーマンス指標のこと 何かを評価するときには何らかの指標(メトリクス)を定めますが、何を指標として設定してどの…
CDNの導入
本来はボトルネックから解消してくべきなのですが限られた時間内でパフォーマンスを改善する必要があったので、とりあえず時間のかかる可能性が高いCDNの導入から行いました。CDNはCloudflareの無料プランを使っています。

若干スコア全体としては上がっているのですが、KPI自体はむしろ悪くなっています。そしてたしか設定をこのときはまちがえていたので、そもそも結果が出ないのは当たり前だったのかもしれません。。(たしか/*とすべきところを/としていてトップページだけをキャッシュしていた。そりゃパフォーマンス変わらんw)
そして、ここでCDNを入れてしまったことにより測定のときにCDNありなのかなしなのかがかなり影響がでるようになってしまいました。。比較する上で同じ条件であることはマストなのに、めちゃくちゃ条件が変わってしまい比較が怪しいところがあります。逆を返せば途中でCDNの設定をいじって正しくキャッシュできるようになった証拠です?w
画像最適化
続いて一番怒られていた画像を最適化してボトルネックを解消していきます。
圧縮
一番怒られていたのは、画像がでかすぎるということだったので画像の圧縮を試みました。圧縮は、これまでに投稿した画像も一括で圧縮してくれるEWWW Image Optimizerというプラグインを使いました。
さらにアイキャッチ画像は多くのページで影響を及ぼすので別途対応しました。背景にグラデーションを使っているものはモノクロのものに比べて圧縮率が悪くサイズが大きい傾向にあったので、モノクロにしできるだけサイズが小さくなるようにしました。一部ブラウザ上の圧縮ツールで圧縮もしました。
努力虚しくあまり結果は変わりませんでした。正直ここで結果が変わらなかったことは最後まで謎でした。。CDNありなしでまだうまく測定できていない状態だったのでこのような結果になってしまったのかもしれません。また、この段階でどうも対応していたはずのLazy Loadが怪しいということに気づきました。
Lazy Load
画像最適化を行うにあたってプラグインをいじっていたところどうもLazy Loadまわりで競合してしまっていたようです。プラグインを整理してLazy Loadを対応させたところそこそこスコアが伸びました。

また、Twitterのembedが時代遅れな仕様でパフォーマンスに影響を与えかねないと思ったので削除しました。ボトルネックになりうる画像が2枚ほどこれで消えました。
WebP対応
圧縮するときにWebpPという次世代のフォーマットに変換することでさらに軽量化を行いました。だいたいどの画像も1/10以下の大きさになっています。圧縮率が高い画像だと1/30ぐらいにまで圧縮できたものもありました。プロキシでリライトするようにして対応していないブラウザではもとのpng/jpegを表示するようにしています。
ページまるごとWebP変換・効果測定と一括ダウンロードがWeb担当者Forumで...…
じわじわとスコアがあがってきました。Speed Indexも当初より1.0 s 以上も早くなりかなり成果が出てきました。
このときのボトルネックとしてはレンダリングをブロックしてる要素があると言われているだけで、画像がでかすぎるとは言われなくなりました!
CDNの最適化
CDNの設定のミスでまったくキャッシュできていなかったので、設定を変更しキャッシュを有効化しました。
かなりスコアが伸びました!スペックの低いサーバーをCDNでカバーすることができているのがわかります。
レンダリングの最適化
続いてもうひとつのボトルネックであったレンダリング(描画処理)の部分を最適化していきます。このあたりからテクニカルになってきます。
クリティカルレンダリングパス
まずは、レンダリングについて知るところからはじめました。クリティカルレンダリングパスとはブラウザ画面を構築するプロセス全体のことをさします。
クリティカル レンダリング パスの最適化は、現在のユーザー操作に関連するコンテンツ表示の優先順位付けを意味します。…
テキストとしてHTML/CSS/JavaScriptファイルを受け取りそれを元にDOMが構築されています。順番に構築していくので途中の特定の処理が全体の演算を止めてしまうことがあります。これがレンダリングブロックであり、パフォーマンスを改善する上で重要なポイントはとしてこの不用意にレンダリングをブロックしている要素を排除することです。具体的には、HTML途中にはいっているなくても動くスクリプトがチューニングする対象です。
非同期ロード
先ほど説明した不用意にレンダリングをブロックしているスクリプトを非同期にロードし実行することでレンダリングのブロックを防ぎより早くユーザーにコンテンツを提供することができるようになります。
<script async src="..."></script>
上記のように記述することでそのような動作が実現できます。
JavaScript allows us to modify just about every aspect of th…
jQueryを非同期にロードする
jQueryはwordpressの標準で読み込まれるようになっていますが、表示だけにはそこまで重要ではない(そうでないなら設計がまずい)ので非同期に読み込んでも問題ありません。また、jQueryを使う処理すべても非同期実行に変更しました。
ただ、これがちょっと曲者でデフォルトで読み込まれるようになっているので、それを解除しつつGoogleのCDNから配信されているjQueryを非同期で取得するという風に変更しました。
Highlight.jsを非同期ロードにする
コードをブログの中で表示するときにHighlight.jsを使っていたのですが、これもレンダリングをブロックしてしまうのとファーストビューにコードが含まれる可能性がかなり低いことを考えて非同期にロードし実行されるように変更しました。
これまでプラグインを使っていたのですが、それもやめて自前実装に変更しています。
ブログの記事内でソースコードをシンタックスハイライトしたくてhighlight.jsを使用しているのですがPageSpe…
余談ですが、この人も同じテーマを使ってるw

CDNなしで測定を行ったのですが、それでもCDNありと同じぐらいの結果が出るようになりました。
CDNが浸透するまで待ってみると、なんとついにKPIであるSpeed Indexが緑色になりました!かなりパフォーマンスが改善されていることがわかります。たのメトリクスもこれに伴って改善されていることがわかります。
札束で殴る
さて、できる限りのことは尽くしたのですが、なかなかこれ以上パフォーマンスを改善することは難しいと薄々気づきはじめました。
そこで
有料テーマを買ってみましたwwwwww
このテーマのすごいところはデフォルトで僕がちまちまやってきたところを一部実装してくれているんですよね。(非同期処理のところ)しかもgzip圧縮やAMP/PWAも対応しているからすごいんです。もちろんSEOも強い。
これと画像最適化とCDNを組み合わせれば最強だろうということで、買ってみましたw
で、結果は、、
さらに10点上がりました!!!
ただ、90点をとって緑にする夢とKPI 2.0 s 以下は残念ながら達成することはできませんでした。。動的な広告を表示しているメディアではこれが限界ぐらいな気がしています。(少なくとも無料CDN+低スペックサーバーなら)その証拠に、
広告を表示していないTopページでは堂々のKPI達成+99点という最強のパフォーマンスを発揮しています。広告なしといってもタグ自体は削除しておらずあくまでAdsense側で配信しないようにしているだけなので、広告タグがなければもっとよい結果になるのだと思います。
ちなみにここまで低速回線でしか試してきませんでした。このスロットリングを無くしてみると、、
1秒以内に記事を表示できているのでかなりいい結果なのではないでしょうか!!
まとめ
やったこと
- CDNの導入
- 画像の最適化
- 圧縮
- Lazy Load
- WebP
- レンダリングの最適化
- jQueryの非同期読み込み
- Hilight.jsの非同期読み込み
- 札束で殴る
- パフォーンマンスのいいテーマに変更
- gzipなどの取り入れ
反省
途中でも述べたようにキャッシュ系を最初にやってしまったことにより、確認しにくくなるだけでなく測定の結果もややこしくなりました。記事にはしていませんが、途中でPWA化もしてキャッシュが効きすぎて効果測定ができないという状況になってしまったので、最後にやるべきだったかなと思っています。(時間の関係で仕方なかったのもあるが)
とはいえ、それ以外のところではボトルネックを洗い出しそれを潰すことでパフォーマンスを改善し定量的に評価するということができたのはよかったかなと思っています。
なにより実際に触りながら勉強できたことで、webにまつわるパフォーマンスの基本を体系的に学べて良かったです。いい勉強になるのでみんさんもぜひ挑戦してみてください!