Category : 開発

最近、GTmetrixPageSpeed Insightsのスコアを上げるのにハマっています。
細かい分析は専門家に丸投げしたいところですが、フロント寄りの人でも対応出来そうな、お手軽な項目をまとめてみました。

この記事に関連のあるキーワード:
NginxSass(Scss)JavaScriptHTML5CSS3UI

目次

GTmetrix、PageSpeed Insightsとは?

フロントエンドの対策

バックエンド(Webサーバー)の対策

WordPressの対策

スマートフォンのUI対策

対応見送り項目

結果

参考になった書籍など

参考サイト

GTmetrix、PageSpeed Insightsとは?

指定したWebサイトの表示速度やパフォーマンスを計測し、改善点を提示してくれるサービスです。会員登録などの手間は一切かからず、無料で利用できます。
今回はここに挙がりがちな問題点のうち、割と簡単にフロント側で修正できそうなものをまとめています。

フロントエンドの対策

document.writeを一匹残らず駆逐

この処理が走るとレンダリングがブロックされます。百害あって一利なしです。速やかに駆逐します。

document.write('hogehoge');
/* ↓↓↓ */
tgtElement.innerHTML = 'hogehoge';

DOMの追加方法はinnerHTML以外にも様々あります。
下記サイトにて、様々な方法で速度テストしていますので、ご参考までに。

外部JavaScriptファイルの非同期読み込みと、読み込ませるタイミングの変更

外部のJSファイルに「async」または「defer」属性を追加して読み込ませることで、レンダリングブロックを回避できます。

<script src="hogehoge.js" async defer></script>

// async:非同期でファイルを読み込み、読み込み完了時に実行
// defer:ページの読み込み完了時に実行

async defer 両方を設定しているのは、どちらか片方しかサポートしていないブラウザのための対策です。
両方サポートしている場合、asyncが優先されるようです。

ただしこのオプションを指定した場合、ファイルの実行順が保証されなくなります。
jQuery等のライブラリに依存している処理がある場合、ライブラリだけは先に読みこませる必要があります。

<!DOCTYPE html>
<html>
<head>
<!-- ライブラリは先に読み込ませる -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<!-- ライブラリは先に読み込ませる -->
</head>
<body>

・・・

<!-- ユーザースクリプトは非同期で読み込ませる -->
<script src="hogehoge.js" async defer></script>
</body>
</html>

</body>直前に非同期で読み込ませるのが最近流行っているようですね。

ソーシャルボタン系スクリプトの対策

Twitter、Likeボタン、はてブボタン等のSNS系ボタンは表示がとても遅いです。
可能な限りページの最下部で、非同期で実行します。

<!-- Twitterボタン -->
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>

<!-- はてブボタン -->
<script src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script>

<!-- ユーザースクリプト -->
<script src="base.js"></script>

</body>
</html>

Facebook Likeボタンは、下記のように「js.async = true;」を追加すると非同期読み込みになるようです。
ただしデフォルトのコードではなくなりますので、FB側で仕様変更があった際には注意が必要です。

<!DOCTYPE html>
<html>
<head>・・・</head>
<body>
<!-- Facebook -->
<div id="fb-root"></div>
<script>
(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.async = true;
  js.src = "//connect.facebook.net/ja_JP/sdk.js#xfbml=1&appId=590342247692699&version=v2.0";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>

CSSのファイル数を減らし、@importを駆逐

@importはスコアが大きく下がる原因ですので、一匹残らず駆逐します。

/* 下記は削除し、可能な限り少ないファイル数でまとめる */
@import url('child.css');

CSSの圧縮(Sass、Compassを利用)

Sass利用前提ですが、今回はクライアントサイドでCSSの圧縮を行ってみます。Compassの設定ファイル(config.rb)で下記設定します。

# config.rb
output_style = :expanded
# ↓↓↓
output_style = :compressed

こんな感じで出力されます。
改行やコメント等も削除され、容量が大体20%前後少なくなります。

Compass、Sassの基礎知識については下記ご参考までに。

CSSスプライト画像の作成

ページ内で使うパーツ系の画像はスプライト画像にします。
サーバーへのリクエスト回数が減り、サーバー負荷が下がります。
Compassを使えば自動でスプライト画像を作成してくれるので、作業時間短縮には必須です。

画像の圧縮

ImageOptim」というソフトを利用します。

画像をドラッグアンドドロップするだけで自動でファイルが圧縮されます。見た目の劣化もほぼありません。
ファイルサイズが10%〜40%くらい軽くなりますので効果絶大です。

バックエンド(Webサーバー)の対策

ここでは主にWebサーバー(Nginx)の設定について記述していきます。
Nginxの設定ファイル(/etc/nginx/nginx.conf)を少しいじります。

gzipでファイルを圧縮し、データの転送量を減らす

Nginxでgzipを使うための設定例です。
※ 状況に合わせて各種パラメータは変更する必要があります

# /etc/nginx/nginx.conf
# httpディレクティブ
http {
#・・・
	# gzipの設定
	gzip  on;
	gzip_http_version 1.0;
	gzip_types        text/plain text/xml text/css text/javascript application/xml application/atom_xml application/javascript application/x-javascript application/x-font;
	gzip_disable      "MSIE [1-6]\.";
	gzip_disable      "Mozilla/4";
	gzip_comp_level   1;
	gzip_proxied      any;
	gzip_vary         on;
	gzip_buffers      4 8k;
	gzip_min_length   1100;
#・・・
}

正しく設定されている場合、レスポンスヘッダに「Content-Encoding:gzip」「Vary:Accept-Encoding」が追加されます。
Chromeのインスペクタにある「NetWork」の各項目にて、レスポンスヘッダを確認できます。

gzipの各項目の詳細は、下記サイトに大変詳しく乗っていますのでご参照まで。

CSSや画像ファイルをキャッシュ

CSSや画像ファイルのレスポンスヘッダに、Cache-Controlヘッダを追加します。

# /etc/nginx/nginx.conf
http {
#・・・
	server {
	#・・・
		server_name www.rokurofire.info;
		location /{
			#・・・

			# 該当する拡張子のファイルキャッシュを30日間有効にする
			location ~ \.(jpg|jpeg|gif|png|css|js|ico)$ {
				add_header Cache-Control "public";
				expires 30d;
			}

			#・・・
		}
	#・・・
	}
#・・・
}

正しく設定されている場合、レスポンスヘッダに「Cache-Control」「Expires」が追加されます。

expires の期間は、1d(1日)だと短すぎるようで、分析サイトでは減点対象となっていました。今回は30d(30日)と多めに設定しています。

また、キャッシュさせたくない場合は public → no-cache にすればOKです。

WordPressの対策

WordPressサイトの場合、下記のような対応が効果的でした。

WP Super Cacheを利用

手軽にWordPressサイトをキャッシュするならこれが一番です。
特に設定を変更しなくても、プラグインを入れて有効にすれば、ほぼ問題ありません。
管理画面から手動でキャッシュクリアもできます。

プラグイン独自のCSSは可能であれば読み込まない

プラグイン独自のCSSを wp_head(); または wp_foot(); あたりで勝手に読み込むので、可能であれば管理画面から削除します。
追加されたCSSの記述を全て使うことは滅多にありません。
とても面倒ですが、必要な分だけをユーザーCSSにコピーして使うか、オリジナルのスタイルを当てるようにします。

CSS/JSの圧縮や非同期対応をプラグインにまかせてしまう

Autoptimize」というプラグインを入れれば、JS/CSS周りは一括でいい感じに非同期読み込み+圧縮をしてくれます。
しかも、jQuery等のライブラリファイルは非同期読み込みから勝手に除外してくれるという、優秀すぎて白目になるプラグインです。
今回は勉強のために自力で対応したかったため、このプラグインは利用していません。

スマートフォンのUI対策

リンクのタップ可能エリア領域を拡大

PageSpeed Insights だと、スマートフォンのUI(UX)についてもスコアリングしてくれます。

タップ可能なエリアが小さすぎたり、場所が近すぎると、警告が表示されます。メッセージを確認しながら適宜CSSで調整します。

ただし、レイヤーを利用して前後に重ねてコンテンツを置いている場合、それらも「場所が近すぎる」と判定されてしまうようです。それらも「場所が近すぎる」と判定されてしまうようです。
特に左右にコンテンツがスライドするUI等を利用している場合は、注意が必要です。

対応見送り項目

広告が document.write している場合など

ここまで色々対策してきてアレですが、広告はどうしようもありません。タグを書き換えたら規約違反になりますし、お金は大事です。
広告でスコアが下がることを見越した上で、他の項目で底上げしましょう・・・

結果

これまでの対策をした結果になります。

GTmetrix

このブログでAAを取れました。ドン!

画像も広告も無いサイトなんだから当たり前だろ!と知り合いに突っ込まれました。

CDNを利用する等の対策でさらにスコアが伸びそうです。
非同期読み込みできないライブラリも、何とか対策できないだろうか・・・

PageSpeed Insights

PCビューのスコアは90を超えました。

GTmetrixと同様に、非同期読み込みできないライブラリが引っかかってます。

モバイルビューの方はまだ改善の余地ありです。
非同期読み込みできないライブラリと、「レイヤーを利用して前後に重ねてコンテンツを置いている」というのがUIの点数を下げていました。

ということで、今回はフロントエンドの人が対応できそうな点をまとめてみました。
規模の大きなサイトやWEBアプリでは、サーバー側のウェイトが大きくなりますが、個人ブログ〜規模の小さな企業サイトなら、このくらいで十分でしょう。

※ 追加記事を書きました → WordPressで、Contact Form 7(プラグイン)が出力するCSS/JSを制御する

参考になった書籍など

参考サイト