WordPressブログにngx_pagespeedを適応してみた

個人的にはあまり体感できていないが速くなったのだろうか。

計測サイトで言われること

以下のようなサイトで計測できる。

結果としてはそこまでひどくはないがモバイル向けに優しいわけではない。怒られているのは以下の様なこと。

  • 圧縮しろ
  • コンテンツの前にJavascript,css入れるな
  • HTML縮小しろ
  • Javascript縮小しろ
  • CSS縮小しろ
  • CSSにクエリストリングつけんな
  • ブラウザキャッシュ有効に使え

gzip圧縮する

とりあえず圧縮しろと言われていてデフォルトでは htmlしかgzipしていなかったのでcssやjavascriptでも行う。

gzipgzip_disable 以外はコメントされていたので、以下のものアンコメントして有効にした。

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

pagespeedでcss/javascriptなどを縮小化する

WordPressの場合、使っているプラグインのCSS/Javascriptが入ってくるのでどうしてもチェックでひかかってしまう。

そこでPageSpeedの出番。PageSpeedはウェブサーバのレスポンスに対して空白を取り除いたり、CSSを縮小かするかなど高速化に必要な処理をウェブサーバ内で自動で変換するツール。ただし自動で変換するのでリスクもある。

Apache版があったのだけどNginxは不安定で今年中にリリースしたい、という話を思い出した。(2013/02/01 Chrome Tech Talk Night #5の時)

Debian向けにDotdebからPageSpeed込のNginxがリリースされていたのでこれを使ってみる。

Nginx 1.4.2 for Wheezy and Squeeze

Nginx 1.4.2 + PageSpeed 1.6.25.9

WordPress向け PageSpeed の設定

サブドメインでサイトを分けていたのでメインはPageSpeed無効にしておき、serverブロックでblogドメインだけ有効にして必要なフィルタをつかうことにする、そのためRewriteLevelにPassThroughをセット。フィルタはcss/javascriptの縮小化とcssの結合、空白とコメントの除去をつかう。ちなみにドキュメントによるとremove_commentsフィルタを使ってもIEコメントは残してくれる。

まとめるとメインのnginx.confのhttpブロック内の設定。

##
# PageSpeed Settings
##   
pagespeed off;
pagespeed FileCachePath /var/ngx_pagespeed_cache;
pagespeed RewriteLevel PassThrough;

blogのserverブロック内の設定。

pagespeed on;
pagespeed EnableFilters combine_css,rewrite_css,fallback_rewrite_css_urls,rewrite_javascript;
pagespeed EnableFilters remove_comments,remove_quotes;
pagespeed RetainComment "* page generated *"; 

RetainCommentは以下のようなSuperCacheの情報などを見たいので追加。

<!-- Dynamic page generated in 0.275 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-10-01 23:20:48 -->

最後にキャッシュディレクトリを作成しておく。

sudo mkdir /var/ngx_pagespeed_cache
sudo chown www-data:adm /var/ngx_pagespeed_cache

PageSpeed Configuration
Configuring PageSpeed Filters

javascriptをフッターへ

コンテンツの描画がブロックされるのでスクリプトをコンテンツの前にいれんなという警告があったので、jQueryをフッターに持っていくようにして、テーマ内のスクリプトも適切に依存関係をつけてフッターに表示されるように修正した。 wp_register_script の最後のフラグが footer に入れるかどうかになっている。

この処理は他のプラグインやテーマの処理に影響を与えるリスクもあるので真似するときは注意してほしい。またjQueryのバージョンもWordPressによって異なるので注意。

function.php
// move jQuery to footer
if (!is_admin()){
  wp_deregister_script('jquery-core');
  wp_deregister_script('jquery-migrate');
  wp_register_script( 'jquery-core', '/wp-includes/js/jquery/jquery.js', array(), '1.10.2', true);
  wp_register_script( 'jquery-migrate', "/wp-includes/js/jquery/jquery-migrate.js", array(), '1.2.1', true );
  wp_enqueue_script('jquery-core');
  wp_enqueue_script('jquery-migrate');
}

wp_enqueue_script('google-code-prettify', get_template_directory_uri() . '/components/js/google-code-prettify/prettify.min.js', array(), '20130305', true);
  wp_enqueue_script('makotokw-script', get_template_directory_uri() . '/style.js', array('jquery', 'google-code-prettify'), '20131009', true);

これに合わせてAmazonJSを完全に依存関係で出力できるように、wp_localize_script をつかうように切り替えた。また余計なことをしたかも。

参考: http://wordpress.org/support/topic/moving-jquery-to-footer

cssの結合

WordPressの出力するcssはidがついていて、id指定で何かをするおそれがあるためpagespeedはidが付いているcssについてはcombine_cssを適応しない。なので結合したい場合はidを取り除く必要がある。

function remove_style_id($link) {
        return preg_replace("/id='.*-css'/", "", $link);
}
add_filter('style_loader_tag', 'remove_style_id');

参考: https://blog.codecentric.de/en/2011/10/wordpress-and-mod_pagespeed-why-combine_css-does-not-work/

まとめと結果

今回やったこと

  • テーマ、自作プラグインを修正して javascript をフッターに移動
  • Nginxの HttpGzipModule で css/javascript などを gzip圧縮して配信
  • ngx_pagespeedで css/javascript の縮小化とcssの結合、htmlの空白・コメントの除去

スコアの変動

  • PageSpeed Insights: Mobile 63/100, Desktop 75/100
  • Page Speed Grade: 85%, YSlow Grade: 75%
  • PageSpeed 1.12 Score: 82/100

適応後

  • PageSpeed Insights: Mobile 80/100, Desktop 92/100
  • Page Speed Grade: 98%, YSlow Grade: 85%
  • PageSpeed 1.12 Score: 97/100

スコアは上がっているけど、普段からスマホで自分のブログを見る機会はないので体感的に早くなったのかはいまいち不明。PCで見る分にはあまり変わらないだろうと思う。ただの自己満足に終わっている感がある。

その他課題

nginxのキャッシュコントロールと、PageSpeedとWordPressのSuperCacheとコンテンツが段階的に配信されているので、意図通りに動いているのか、無駄なことをしていないかちょっと図りかねているところがある。とりあえずPageSpeedはキャッシュが目的のモジュールではないし、DBアクセスを減らすためSuperCacheは入れておいて良いだろうと思っている。キャッシュコントロールのヘッダがどうなっているかチェックする必要がありそう。