PageSpeed Insightsで100点を出してみた

ブログの表示が遅い・・・。ブラウザが読み込みはしているけど、白い画面のまま何も表示されない・・・。モバイルファーストと叫ばれているので気をつけてはいるけど、1ページの容量が数MBと凄く大きくなってしまう・・・。

ある時に、自分のブログを外出先からスマホで見てみようと思ったら、表示されるまでに時間がかかり遅い事が分かったので、勉強も兼ねてブログの高速化に取り組んでみました。

高速化の指標とした2つのサイト

PageSpeed Insightsでの指摘事項を1つ1つクリアしながら、GTmetrixの「Waterfall」「Page Load Time」をチェックしながら進めました。

まずは結果

このブログはほぼ100%、GoogleとYahooからの検索流入が全てなので、トップページではなく各記事のページを早くすることを意識しました。

高速化に取り組んだ結果は、

20160108s2

20160108s1

PageSpeed Insightsが、モバイルとPCで100点。

20160108s3

GTmetrixが、PageSpeedとYSlowでA判定。(画像をもう少し圧縮できるはず・画像でCDNを利用してみては・cssの細かい指摘、という3つの努力目標が残っています)。

後で書きますが、「アクセス解析のAnalytics」と「広告のAdSense」を利用していると、PageSpeed Insightsで100点が出なかったので、一時的に2つとも外した状態が上記のスクリーンショットの点数です。通常はAnalyticsとAdSenseを利用しているので、90点前後の表示が出ます。

高速化で取り組んだ内容

  1. WordPressで利用していないプラグインを停止する
  2. WordPressで利用していない機能がヘッダーとフッターで出力されるのを停止する
  3. レンダリングをブロックしているJavaScript/CSSを排除する
  4. 画像を最適化する
  5. ブラウザのキャッシュを活用する
  6. 圧縮を有効にする
  7. その他

*3~6項は、PageSpeed Insightsの指摘事項

上記の7つの作業を行ったので、1つ1つ記載していきます。

1:プラグインを停止する

WordPressは動的CMSなので、アクセスがあってから最初のhtmlファイルをブラウザに返すまでに、PHPの解析をしたりデータベースから文章を引っ張り出してきたりと色々な動作をしています。そのたびにプラグインが介在していては動作が重くなるのは何となく想像できるので、使用していないプラグインは全て停止してみました。(1アクセス毎にhtmlファイルを作成していては負担が大きいので、htmlファイルをキャッシュするプラグインがあったり、レンタルサーバ側でキャッシュ機能を持った会社もあります。)

このブログで利用しているプラグイン5つ

  • WP Multibyte Patch
  • TinyMCE Advanced
  • WordPress Ping Optimizer
  • Google XML Sitemaps
  • Contact Form 7

プラグインによっては「外部cssやjavascript」を読み込んだりするので、PageSpeed Insightsの「レンダリングをブロックしているJavaScript/CSSを排除」にも関係するので、プラグインの見直しは必須だと思いました。

2:Wordpressで使用していない機能が、ヘッダーとフッターで出力されるのを停止・制御する

ブラウザの「ページのソースの表示」で、ヘッダーとフッター部分を1行ずつ見ていき、必要ないなと思う機能を削除しました。高速化とは関係ないかもしれませんが、htmlのサイズ縮小にはなるかと・・・。

「wp_head();」で出力されないように停止した内容

ヘッダーの「wp_head();」で出力されないように、funcitions.phpへ下記を記載しました。

//利用させていただいているテーマのStinger5に最初から記載
remove_action( 'wp_head', 'feed_links_extra', 3 );
remove_action( 'wp_head', 'feed_links', 2 );
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'index_rel_link' );
remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 );
remove_action( 'wp_head', 'start_post_rel_link', 10, 0 );
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
remove_action( 'wp_head', 'wp_generator' );
//高速化で追記
//絵文字関係
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('wp_print_styles', 'print_emoji_styles' );
remove_action('admin_print_styles', 'print_emoji_styles');
//Wordpress4.4からのoembed関係
remove_action('wp_head','rest_output_link_wp_head');
remove_action('wp_head','wp_oembed_add_discovery_links');
remove_action('wp_head','wp_oembed_add_host_js');
remove_action('wp_head','wp_shortlink_wp_head');

Contact Formの機能を必要なページだけで読み込み

プラグインの「Contact Form」を利用すると、全てのページでContact Formを読み込んでしまうので、「functions.php」へ下記を追記し「お問い合わせページ」のみで読み込むように変更。このブログのお問い合わせページは、「固定ページ・IDが84です」。

function deregister_cf7_files() {
    if ( ! is_page(84) ) {
        wp_dequeue_style( 'contact-form-7' );
        wp_dequeue_script( 'contact-form-7' );
    }
}
add_action( 'wp_enqueue_scripts', 'deregister_cf7_files' );

3:レンダリングをブロックしているJavaScript/CSSを排除する

高速化の中で一番困ったのが、PageSpeed Insightsのこの指摘事項。少しブログをいじると表示がおかしくなって、あっちをいじるとこっちが・・・。と、スパイラルにハマった指摘事項です。

最初は、「レンダリングをブロック??」「排除??」と、言葉の意味が分かりませんでした・・・。そして1週間ぐらい悩んでも分からなかったので、こういう事に詳しい友人に相談して丁寧に教えてもらいました。

ブラウザのChromeで、レンダリングのブロックを体感

そもそもの意味が分からないなら体感するのが一番ということで、ブラウザのChromeで「帯域制限」を利用して「レンダリングのブロック」を体験してみました。

20160108s4

メニューバーの「表示」から「開発/管理」、「デベロッパーツール」を選択。

20160108s5

「No throttling」という部分をクリック。

20160108s6

「Add」を選択。

20160108s7

とにかく遅い状態にしたいので、仮に「10kb/s」・Latencyは「900ms」としてみました。

20160108s8

作成した「Throttling Profiles」を選択。これで帯域制限状態になります。この状態で、ご自身のサイトにアクセスをしてみてください。

いかがでしょうか?

最初に「htmlファイル」が読み込まれ、次に「cssファイル」や「jsファイル」が読み込まれているけど、画面は何も表示されない状態が凄く長く続くと思います。やっと表示されても、画像ファイルが続けて読み込まれていて、いつになったら読み込み完了するのかが分からない状態になりませんか?

この、最初に何も表示されない空白の状態が「レンダリング(描画)がブロックされている」状態です。

スマホで月間の通信容量をオーバー、帯域制限された状態だと、このChromeの帯域制限と似たような状態です。待てど暮らせど何も表示されない・・・。

対策した内容

1m秒でも早く何かしらを表示する、せめてブラウザで最初に表示される部分(ファーストビュー)だけでも先にレンダリング(描画)をする、そのために「htmlファイルが読み込まれたら最初の描画が開始できるようにしなさい。」「最初に必要ない外部スタイルシートやJavascriptなどは、最初の描画に関係無いですよとhtmlに記載をして、後で読み込ませて描画するようにすればいい。」というのがPageSpeed Insightsのこの指摘事項のようです。

なので以下の対策を実施しました。

*サイト構成や使用しているWordPressのテーマ・プラグインで対策方法は違ってきます、どこかで妥協しないといけない凄く難しい指摘事項だと思います。

CSSをインライン化と非同期で読み込み

PageSpeedの解説で、ブラウザで最初に表示される部分(ファーストビュー)を「htmlファイル」にインライン化。残りの部分は外部スタイルシート「cssファイル」で非同期で読み込む。

とあったので、言う通りに実施。

*外部スタイルシートのほうが、「2回目の訪問からブラウザのキャッシュが効いて速い」という記事も読みましたが、とりあえずPageSpeedの言う通りに。

*「DOMツリー構築後に〜」という友人からの指摘もありましたが、非同期で後からCSSを読み込むと、読み込み完了後に再描画がかかります。状況によってはガクッと画面全体が揺れたり、意図しない表示になる場合があります。

CSSインライン化

最初に表示される部分(ファーストビュー )だけのスタイルを抜き出すのが面倒だったので、「cssファイル」からざっくりと抜き出してインライン化しています。

インライン化する部分を下記のサイトで圧縮(Minify化)。

「header.php」の「<head>〜</head>」の中に下記を記載。

<style type="text/css">
ここに圧縮したcssを記載
</style>

これでインライン化が完了。

CSSの非同期読み込み

上記でインライン化した以外のスタイルは、今までどおり「style.css」に記載のままでいいのですが、「このcssファイルの読込みが完了するまで描画が開始できない!」と、PageSpeedに指摘されるので、「描画に関係ないですよ」という形で非同期で読み込ませます。

「footer.php」の「</body></html>」の前に、下記のように記載。

<script>
(function(d){
var s = d.getElementsByTagName('script')[0];
var c1 = d.createElement('link');
c1.rel = 'stylesheet';
c1.href = '<?php echo get_stylesheet_uri(); ?>';
s.parentNode.insertBefore(c1, s);
})(document);
</script>

「<?php echo get_stylesheet_uri(); ?>」を、「http://~/style.css」と記載しても大丈夫です。

*「style.cssファイル」の中身も、圧縮(Minify化)しておいたほうがいいです。

これで非同期読み込みになります。

Jsファイルの削除

各ページで共通して読み込まれる「jsファイル」は、「Analytics」と「Adsense」のみになりました。

*「お問い合わせページ」でのみ、プラグインの「Contact Form」を読み込んでいますが、Contact Form自身がJqueryを読み込みます。なので、お問い合わせページでは引き続き「レンダリングをブロックしている〜」の指摘事項が出ます。

*Adsenseを表示している時は、「非同期タグ」を利用。「同期タグ」だと、Adsenseの読み込みが完了するまでブラウザの描画がはじまりません。

4:画像を最適化する

Macで「JPEGmini」を利用し画像を圧縮していますが、「まだ圧縮できるよ!」と指摘されたので、「ImageOptim」でさらに「85%」の圧縮をしています。

20160108s10

ImageOptimの環境設定で、JPEGの品質を85%にしています。

5:ブラウザのキャッシュを活用する

利用しているレンタルサーバーは「WPXレンタルサーバー」です。.htaccessに以下の内容を記載し、ブラウザのキャッシュを利用するようにしました。

# ブラウザキャッシュの設定
<IfModule mod_headers.c>
<IfModule mod_expires.c>
ExpiresActive On
# MIME Type ごとの設定
ExpiresByType text/css "access plus 1 weeks"
ExpiresByType text/javascript "access plus 1 weeks"
ExpiresByType image/gif "access plus 1 weeks"
ExpiresByType image/jpeg "access plus 1 weeks"
ExpiresByType image/png "access plus 1 weeks"
ExpiresByType image/svg+xml "access plus 1 weeks"
ExpiresByType application/pdf "access plus 1 weeks"
ExpiresByType application/javascript "access plus 1 weeks"
ExpiresByType application/x-javascript "access plus 1 weeks"
ExpiresByType application/x-shockwave-flash "access plus 1 weeks"
ExpiresByType application/x-font-ttf "access plus 1 weeks"
ExpiresByType application/x-font-woff "access plus 1 weeks"
ExpiresByType application/x-font-opentype "access plus 1 weeks"
ExpiresByType application/vnd.ms-fontobject "access plus 1 weeks"
</IfModule>
</IfModule>

キャッシュの有効期限を1週間以上にすると、PageSpeed Insightsの指摘がなくなるようです。

6:圧縮を有効にする

ブラウザのキャッシュと同じように、.htaccessに以下の内容を記載しGzip圧縮を有効にしました。

# Gzip圧縮の設定
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
# 画像など圧縮済みのコンテンツは再圧縮しない
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary
# プロクシサーバーが間違ったコンテンツを配布しないようにする
Header append Vary Accept-Encoding env=!dont-vary
#圧縮対象とする MIME Type
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-font-woff
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
</IfModule>

7:その他

「WPXレンタルサーバー」は、Wordpressのキャッシュ機能を標準で備えていて「ON」になっているのでそのままに。他にも「mod_pagespeed」が利用できるので、「ON」にしています。mod_pagespeedのフィルターはまだまだ試行錯誤中ですが、.htaccessに以下の内容を記載しています。

ModPagespeed On
ModPagespeedDisableFilters convert_jpeg_to_webp,convert_to_webp_lossless
ModPagespeedDisableFilters rewrite_images

MacのSafariは画像ファイルの「Webp」に対応していないようですが、なぜかModPagespeedがWebpを出力してしまい、画像が何も表示されないという事があったので変換を停止。これ以上画像を圧縮してほしくないので、Rewriteを停止。

高速化後のGTmetrixのWaterfall

上記までの対策をしたWaterfallは以下の画像。

20160108s9

DOM Loadedが500msぐらいになりました。

AnalyticsとAdSense

AnalyticsとAdSenseを利用していると、「ブラウザのキャッシュを活用する」や「画像を最適化する」の指摘事項がクリアできないのですが、外部ファイルでいじれないので仕方がないようです。

そして、AdSenseで配信される広告によっても読み込む容量が大きく変わります。1回目の計測で95点!2回目の計測で85点・・・。と全然点数が変わったりします。「テキスト広告」・「ディスプレイ広告」でも大きく違いが出ます。

スピードを求めてサイトを改造する時は一時的にAdSenseを外しておいたほうが、どこまでが自分で追い詰められる範囲かが分かりやすいかもしれません。

まとめ

言葉の意味が分からない状態から、一つ一つ調べて対策をしたので、1か月近くの時間がかかりました。

パソコンでインターネットを利用していると忘れてしまいがちですが、Wifiのない環境でスマホでサイトを閲覧していると、画像やなんだかんだで数MBのサイトは、7GB(キャリア)や2GB・1GB(MVNO)の通信容量を考えるとキツイなと思いました。

そして、サイトの最初の部分だけでもとにかく早く表示させようという大切さも今回のことで学びました。

仕事でサイト立ち上げ・運営などをしている友人からは「趣味でやっているブログなんだから、細かいことは気にしなくていい。強いてあげれば画像の容量だけ気をつける。それよりも、人に伝えやすい文章を書くことに時間を使ったほうがいいと思うよ。サイトの高速化は、企業や商用サイトで、お客様に対して1msでも早く表示する!という時にガリガリやればいい。」というアドバイスが・・・。

色々学べて知識もつきましたが、削ることに専念してなんだか寂しいブログになってしまったので、次はもっとインタラクティブなブログを目指してみたいなと思います。

画像も圧縮しすぎで汚く・・・。もっと綺麗に表示したい・・・。

「サイト高速化」と「ブログのオリジナリティ」の妥協点を見出すのは、なかなか難しそうです。