WordPressは一般的に重いと言われているが、きちんと使えば高速なウェブサイトを作り出すことができる。重いウェブサイトはSEO的にもマイナスに働くため、できる限り高速化しておくことが望ましい。事実、わずか数秒の差がユーザの離脱に直結するなどの明らかな統計が出ており、とくに回線の遅いモバイルについてはその差が顕著に現れる。
ところが、実際にWordPressを高速化しようとGoogleで検索してみると、画像圧縮やキャッシュプラグインの紹介などが多く、それだけでは最適化としては不十分だ。そこで、この記事ではぼくが新規ウェブサイトを立ち上げるにあたり、PageSpeed Insightsでスコア100を実現するために行ったすべての手順を紹介する。
あなたのサイトは、いまどうなっているのか。まずは現状を把握しよう
作業を行う前に、現状がどうなっているのかを確認しよう。測定ができるツールやサービスはたくさんあるが、今回は次の2つのツールを使って実態を把握してみる。
PageSpeed Insights
PageSpeed InsightはGoogleが提供しているオンラインサービスで、ウェブサイトの速度を計測してスコアリングし、改善点を指摘してくれる便利なツールだ。サイトのURLを入力するだけの簡単操作なのでぜひ実行してみてもらいたい。
ここで、重要なのはスコアではなく、問題があったときに提案される改善案だ。
「修正方法を表示」をクリックすれば詳細を見ることができるが、多分さっぱりわからないと思うので、ここではあまり気にしなくていい。この記事では、Googleが提案してくれるこれらの改善点を一つずつ対応していくことでスピードアップを図る。
最初に断っておくが、ここで100点を出すことが目標ではない。満点を出しても何の意味もないので、そこにとらわれないようにしよう。
P3 – Plugin Performance Profiler
P3 – Plugin Performance Profilerは、WordPressのプラグイン実行にかかっている時間を計測してくれるプラグインだ。インストールしたら、Start Scan→Auto Scanとたどることで計測が開始される。上の画像は、このサイトでP3を走らせたときの結果だ。
WordPressを重くする一つの要因は、このプラグインにある。プラグインは機能を手軽に追加できるためとても便利な反面、多用するとページ表示速度がどんどん落ちていく。
上部にあるPlugin Load Timeに注目しよう。その名のとおり、実際にすべてのプラグインがロードされるまでにかかる時間を示している。
この数値が0.2秒を超えていると、すでに危ない。Googleはサーバが応答する理想を0.2秒以内と定めている。したがって、プラグインだけで0.2秒を超えていると、当然全体で0.2秒という基準を満たすことができなくなるからだ。
プラグインを整理し、本当に必要なものだけを残す
まず、使っていないプラグインはすべて停止してしまおう。いらないなら潔く削除してしまってもいい。
さらに、現在使っているプラグインが本当に必要かを考え直そう。導入してはみたものの、あまりユーザに使われていなかったり、いまいちだけど放置しているものがあるかもしれない(なお、管理画面でしか使わないプラグインを削除してもページ表示速度には影響しないが、ここで整理するのもありだろう)。
ここまでは誰にでもできるが、この先は少し大変だ。
プラグインに頼りすぎない
個人で作成するにはとても時間がかかったり、難度が高かったりするものは、プラグインに頼るほうがコスパがいいに決まっている。しかし、ちょっとした機能までプラグインに依存するのは考え物だ。たとえば、次のような機能をプラグインで実装していたりしないだろうか。
- ページネーション
- 「次の記事」リンクの追加
- 最新の投稿にサムネイルを表示
- カスタム投稿の追加
- FacebookやTwitterへのシェアボタン追加
- サイトマップ(sitemap.xml)の作成
- Google Analyticsコードの追加
挙げだすときりがないが、このような細かい機能はプラグインを使わなくてもコードを少し修正すれば実装することができる。というかほぼコピペでいける。
最初のページネーションは、次のような数行のコードをfunctions.phpに記述し、使いたいところで呼び出せばいいだけだ。
function get_pagination($pages = 5) {
?>
<div class="pagination">
<?php
global $wp_query;
$big = 999999999;
echo paginate_links(array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'mid_size' => $pages,
'total' => $wp_query->max_num_pages,
'prev_text' => 'Prev',
'next_text' => 'Next'
));
?>
</div>
<?php
}
このようなコードスニペットは、ウェブ上にいくらでも転がっている。You Might Not Need That WordPress Pluginなんかは特に有名だ。
自分で実装できそうなものはコードを書き、プラグインを減らしていこう。ただし、下手に自前でやろうとして逆に重くなることもないとは言えないので、無理はしないようにしよう。
重いプラグインを見直す
機能が豊富なプラグインは、たいていの場合重いということを念頭に入れておこう。たとえば、SEO対策で最も有名なAll in One SEO Packを導入すると、それだけでプラグインのロード時間は跳ね上がる。上の赤い部分が該当箇所だが、単体で0.1秒近くを消費する。SEO対策についてはまた別の記事で書こうと考えているが、何をすればSEOとして効果的なのかを理解せずにプラグインだけ導入しても意味がない。
ほかにも、Yoast SEOやJetpackなどは便利だが重たい。おすすめのプラグイン紹介などでたびだび登場するので導入しているサイトも多いが、あなたのサイトに本当に必要かは今一度考え直してみてほしい。必要な機能を、必要最低限のプラグインで実現できるのが理想的だ。
P3を利用すればどのプラグインが重いかはわかるはずなので、同等の機能をもつ軽いプラグインやライブラリに乗り換えることも有効だ。たとえば、ソースコードをきれいに表示するためのSyntaxHighlighter EvolvedやCrayon Syntax Highlighterは重いのでPrism.jsを利用する、という例が挙げられる。代替案は検索すれば出てくるので、「軽い」というキーワードを入れて調べてみよう。
ちなみに、ぼくはSEOパック系にはさよならをし、自分でプラグインを作った。自分に必要な機能しか入っていないので、とても軽い(が、きちんと動作しているか時間をかけて検証中だ)。
WordPress標準の不要な機能を削除する
プラグインのダイエットが終わったら、今度はWordPressが標準で読み込んだり書き出したりする機能の中で、不要と思われるものを抑制していく。万一動かなくなると問題なので、しっかり動作確認をしながら進めてもらいたい。
Emojiなどの不要な機能を削除する
functions.phpに以下のコードをコピペするだけでよい。
/*
Remove the emoji javascript
*/
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
/*
Remove unnecessary meta data / link tags
*/
remove_action( 'wp_head', 'wlwmanifest_link');
remove_action( 'wp_head', 'rsd_link');
remove_action( 'wp_head', 'wp_generator');
Emoji、WordPressバージョン、Windows Live Writerなどの出力を削除している。
jQuery Migrateを読み込まないようにする
jQuery Migrateは古いバージョンのjQuery機能を使えるようにするライブラリだが、最新のプラグインなどを利用している限り、必要になることはまずない。
/*
Supress loading jQuery Migrate
Load jQuery on the footer instead of the header.
*/
function enqueue_jquery() {
wp_deregister_script( 'jquery' );
wp_deregister_script( 'jquery-migrate' );
wp_enqueue_script( 'jquery', includes_url( '/js/jquery/jquery.js' ), false, NULL, true );
}
add_action( 'wp_enqueue_scripts', 'enqueue_jquery' );
ついでに、jQuery本体をヘッダーではなく後で読み込むように変更している。もしjQuery自体不要な場合は、最後の一行を削除すればよい(関数名がちょっとおかしくなるが)。
functions.phpにコードを記載していくと肥大化し、管理がしにくくなる。機能別にphpを分け、libフォルダにいれておくといいだろう。
今回の場合は、たとえばinitialize.phpなどとし、require_once( __DIR__ . '/lib/initialize.php' );
をfunctions.phpに記述して読み込めば使えるようになる。
プラグインが読み込むCSSを読み込まないようにする
たとえば、WordPress Popular Postsというプラグインは、スタイルを適用するためにCSSを読み込む。しかし、自分のサイトを作る場合は、プラグインデフォルトのCSSを使わず、自分のCSSで見た目を整えている場合も少なくない。
こうなると、元のプラグインのCSSは不要なのに読み込まれる状態になってしまう。
プラグインによっては、設定画面でスタイルシートを無効にできる場合がある。WPPの場合も、Use plugin’s stylesheetをDisabledにするとwpp.cssは読み込まれなくなる。
設定でできない場合は、コードで抑制できる。
/*
I don't like these styles. I use my own ones alternatively.
*/
function dequeue_styles() {
wp_dequeue_style( 'handle-name' );
wp_deregister_style( 'handle-name' );
}
add_action( 'wp_enqueue_scripts', 'dequeue_styles' );
handle-name
は、headerタグ内に出力されるlinkタグのidと一致しているはずなので、ブラウザのデバッグモードで調べることができる。
なお、プラグインによってはadd_actionにPriorityを指定する必要がある。
ソースコードを縮小する
今度は、PageSpeed Insightsの次の提案に対応していこう。
- CSS を縮小する
- HTML を縮小する
- JavaScript を縮小する
縮小する(Minify)とは、コード内の不要なスペースやタブなどを削除することを意味する。
.not-found-container .not-found-wrapper .not-found-bottom p{line-height:120%}.not-found-container .not-found-wrapper .not-found-bottom a{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;height:40px;line-height:40px;margin-top:10px;padding:0 20px;color:#fff;-moz-border-radius:20px;-webkit-border-radius:20px;-o-border-radius:20px;-ms-border-radius:20px;border-radius:20px;border:1px solid #ebeff0}
人間にとっては読みにくくなるが、コンピュータには全く関係ない。WordPressの場合、すべて一括してMinifyしてくれるすばらしいプラグインがある。
使い方はとてもシンプルだ。インストールしたら、上のバーに現れるAutoptimizeをクリックして設定画面を開こう。
HTML、JavaScript、CSSのすべてにチェックを入れて保存するだけでよい。実際にソースコードを確認すると、縮小されているのを確認できるはずだ。
なお、JavaScriptを最適化すると、コードの書き方によっては、まれに動作がおかしくなったり、動かなくなったりする場合があるようなので、不具合がないか必ず確認しよう。
Autoptimizeはデータをキャッシュする。もしスクリプトやCSSを更新しても反映されない場合は、トップバーのAutoptimizeから「キャッシュの削除」をクリックしてみよう。
画像を圧縮する
JPEGやPNGはすでに圧縮されているのだが、ここではGoogleが理想とする基準にまで圧縮することを目標とする。プラグインで解決を促すサイトが多いが、それだけでは不十分だ。
少し手間がかかるが、下の内容を参考にし、順を追って実行してみてほしい。
サムネイルの画質を落とす
記事のサムネイルなどを一覧で表示している場合、少し小さめの画像を使うことは多い。このサムネイルは、WordPressが自動で生成してくれているものを使用しているはずだ。
この画質は、デフォルトでは90に設定されているので、70程度まで落とそう。どうせ小さいし、見た目はほとんど変わらない。
/*
Change the quality of featured images
*/
add_filter( 'jpeg_quality', function( $args ) { return 70; } );
functions.phpに一行コードを追加するだけだ。
JPEG画像をアップロードするときは、先に品質を落としておく
画像の圧縮は次で説明するEWWW Image Optimizerを使うのだが、JPEG画像の場合、無料版だと圧縮が不十分でPageSpeed Insightsの基準は満たせない(品質を維持しようとする力が働く)。
ここでは、Ralpha Image Resizerという一括リサイズ、圧縮ツールが便利なので紹介しておく。
インストール不要で、exeをダブルクリックすればすぐに使える。
起動したら、Sizeを”Percent”にし、Scaleが100%になっていることを確認する。
次に、”Settings”から”JPEG Settings”とたどり、JPEG用の設定を開こう。
“Quality”を80にし、”Always recompress“のチェックを入れて、OKを押せば設定は完了だ。画像を放り込んで、”Convert”から”Run”すればよい。
すでにアップロードしている画像は面倒なので放置してもよいが、ちゃんとしたい場合はこのツールで圧縮しなおすこともできる。
WordPressの画像は、wp-contentsフォルダの中のuploadsというフォルダにまとまっている。FileZillaなどのFTPソフトで一度すべてダウンロードし、Ralphaで一括圧縮後、再び同じ場所にアップロードするだけだ。10分もあればできるだろう。
ぼくの場合は80で問題なかったが(80でも150KB→40KBとかなり容量は削減される)、あとで不十分だとわかったらもう少し落としてみよう。
EWWW Image Optimizerを導入する
EWWW Image Optimizerは、アップロードする画像を自動で圧縮してくれるほか、すでにアップロードした画像も一括して最適化してくれる機能を持つ(前述のとおり、JPEGの場合は元の画像の品質が高いとGoogleの基準は満たせない。PNGはうまく圧縮できる)。
たくさん設定があるのだが、デフォルトのままでかまわない。
メディアから「一括最適化」を選べば、これまでにアップロードしたすべての画像の最適化を行える。「最適化されていない画像をスキャンする」ボタンを押し、スキャンが終わったら「最適化を開始」するだけのお手軽操作だ。
これで、画像への対応は終わった。なお、画像の品質にこだわりがある方は、EWWW Image Optimizerだけでも導入しておこう。ロスレス圧縮なので、品質は低下しないが容量は削減することができる。
レンダリングをブロックする要素を排除する
外部JavascriptやCSSをHeader内で読み込むと、読み込みが終わるまでページを表示することができない。このことを「レンダリングをブロックする」とGoogleは表現している。
先ほどのAutoptimizeがJavascriptをFooterで読み込むようにしてくれているので、残っているのは一つのCSSファイルだけなはずだ。ところが、CSSファイルを後で読み込むとスタイルが適用されていない状態で表示されるため、見た目としては望ましくない。
従って、CSSをインライン化することで対応する。「CSSをインライン化する」とは、HTMLのHeaderにCSSを直接記載することを意味する。しかし、今さら書き換えるのは面倒だし、管理上の問題もある。
ここでも、Autoptimzeの出番だ。
Autoptimizeの設定画面右上に「高度な設定を表示」というボタンがあるので、クリックする。CSSオプションから「すべての CSS をインライン化」にチェックして保存するだけだ。
説明にもある通り、この設定は逆効果になる可能性があり、特にCSSのファイルサイズが大きい場合は注意が必要だ。ぼくの元のCSSファイルサイズは70KB程度だが、今のところ問題は発生していない。いつでも元に戻せるので、設定をして様子をみるのもありだろう。
サーバの設定を変更する
終わりが見えてきた。もう少しなので頑張ってほしい。最後に、Googleの提案する次の2つの項目に対応していこう。
- ブラウザのキャッシュを活用する
- 圧縮を有効にする
ブラウザのキャッシュとは、一度ダウンロードした画像などを再度サーバに取りにいかず、ローカルで一時的に保存したデータを使用することを意味する。画像やウェブフォントなどは頻繁に更新しないので、キャッシュを利用すると高速化にきわめて有効だ。
2番目の「圧縮を有効にする」とは「データを送信する際にサーバで圧縮し、ブラウザで解凍して表示する」機能を有効にすることで、gzipという技術を用いる。
WordPressにはキャッシュ系のプラグインがたくさんあるが、扱いが難しいのであまりおすすめできない。ここでは、.htaccessを修正して対応する。Apacheサーバを対象とするため、Nginxの場合は自分で調べてほしい(さくらインターネットやエックスサーバなど有名なレンタルサーバはすべてApacheが動いている)。
.htaccessをダウンロードする
.htaccessファイルは、WordPressがインストールされているルートフォルダに存在するはずだ。wp-contentやwp-adminフォルダと同じ階層にある。
エックスサーバの場合は、public_htmlの中に入っている。FTPソフトでダウンロードしたら、どこか別の場所にバックアップをとっておこう。設定に失敗するとサイトにアクセスできなくなるので、面倒でも必ず退避させておいてほしい。
編集用のファイルをSublime Textなどで開くと、Permalinkを有効にしている場合は次のようになっているはずだ。
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
このEND WordPressより下に新たにコードを記載する。WordPressの中に書くとコードが上書きされて消えてしまうので注意しよう。
圧縮・キャッシュコードを追加する
ぼくはあまりApacheには親しみがないので、解説サイト(こことかこことかいろいろ)やドキュメントを見ながら設定した。Apache公式ではこことかここに書いてある。
最終的には、次のように書けばよいことがわかった。
# Header configuration
<IfModule mod_headers.c>
Header unset ETag
Header set Connection keep-alive
</IfModule>
FileETag None
# Ensure that server knows these MINE types
<IfModule mime_module>
AddType image/x-icon .ico
AddType image/svg+xml .svg
AddType application/vnd.ms-fontobject .eot
AddType application/x-font-ttf .ttf .ttc
AddType application/x-font-opentype .otf
AddType application/x-font-woff .woff
AddType application/x-font-woff2 .woff2
AddType text/cache-manifest .appcache
AddEncoding gzip .svgz
</IfModule>
# Cache control
<IfModule mod_headers.c>
# Cache image and fonts
<FilesMatch "\.(ico|jpe?g|png|gif|svg|swf|pdf|ttf|woff|woff2|otf|eot)$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>
# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary
Header append Vary Accept-Encoding env=!dont-vary
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 seconds"
ExpiresByType text/css "access plus 1 days"
ExpiresByType text/js "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 year"
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 year"
ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType application/x-font-woff2 "access plus 1 year"
ExpiresByType application/x-font-opentype "access plus 1 year"
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
</IfModule>
# Enable gzip conpression
<IfModule mod_deflate.c>
# Avoid some problems of old browsers, like Netcape
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# Don't append Vary header for specific files
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|zip|lzh|exe|woff|woff2)$ no-gzip dont-vary
# For older version of Apache which doesn't support the filter module
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml text/js text/x-component
AddOutputFilterByType DEFLATE application/javascript application/json application/x-javascript
AddOutputFilterByType DEFLATE application/xml application/rss+xml
AddOutputFilterByType DEFLATE application/xhtml+xml application/atom+xml
AddOutputFilterByType DEFLATE image/svg+xml image/x-icon
AddOutputFilterByType DEFLATE application/x-font-ttf application/x-font-opentype
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
</IfModule>
このコードをすべてコピペしたら、FTPソフトで再びアップロードしよう。これで、サーバの圧縮とキャッシュが働いているはずだ。
それぞれのファイルのキャッシュ期間は運用するサイトによってカスタマイズされるべきであるが、おそらくそのままでも大丈夫だろう。
キャッシュを有効にすると、画像などを上書きしてもすぐには反映されなくなる。すぐに反映させたい場合は、異なる名前で新規のファイルとしてアップロードしよう。
自分で確認するときは、Chromeの「検証」を有効にしてリフレッシュボタンを長押しすると、「キャッシュの消去とハード読み込み」という項目が選択できるようになる。
いくつかの補足
その他、いくつか補足しておきたいと思う。
処理の速いサーバを利用する
サーバの性能は、当然応答時間に影響する。WordPressはphpの処理が必要なので、性能の高いサーバをレンタルすることも重要だ。
いままで使った中では、エックスサーバがベストだ。このサイトもエックスサーバを利用している。料金が割高なのが多少ネックだが、その分信頼できるので、これからサーバを選ぶ方はぜひ検討してみてほしい。
また、CDNというサービスを利用して、静的なファイルを高速にユーザに届けることも考えられる。個人のサイトでそこまでやる必要はないかもしれないが、企業サイトや、ギャラリーサイトなどは導入を検討してもいいだろう。CloudFlareは無料でCDNサービスを提供してくれている。
画像の遅延読み込み
画像自体を最適化していれば、ほとんどの場合必要になることはないと考えられるが、画像を遅延読み込みさせることでページ表示速度をさらに向上することができる。
ユーザがスクロールをし、画像に近づいたらロードする仕組みなので、最初のページ表示が速くなるというわけだ。
Google Analyticsなど外部サービスと連携する場合
Google Analyticsを導入する場合、スコア100を目指すことはできない。皮肉なことに、analytics.jsというファイルのキャッシュ有効期限が短いため、PageSpeed Insightsの得点が1減ることになる。また、外部サービスと連携する、たとえばAdSenseやAmazonアソシエイトなどを使う場合も、おそらくスコアが下がることになるだろう。このあたりはあがいても無意味なので、導入する際はスコアを気にするのはやめよう。
おわりに
この記事の内容をすべて実行できれば、PageSpeed Insightsのスコアはかなり上昇しているはずだ。うまくいけばモバイルでも90点を超えられているかもしれない。
より詳細に最適化を進めたい場合は、GTmetrixというサイトで計測してみるとよい。かなり細かく改善点を教えてくれるはずだ。
もちろん、すべての項目を実現するには無理な場合も少なくないだろう。速度を上げることは大切だが、それ自体がサイト運営の目的ではない。良質なコンテンツを提供すれば、多少遅くとも人はくるのだ。最適化は「自分にできる範囲で、できる限りやる」にとどめておくことをおすすめする。