2013.11.23 追記
誤った使い方であるという指摘がありました。
一読の価値はあるかなと。Mozilla さんの書き方がよろしくないとも言及されてます。
http://tech.no-delay.com/?p=694
2013.12.05 追記
上記サイトが閉鎖?されていました。
テーマが少し一段落。
出来得る限りの表示スピード改善も一段落。
ということで表示速度を少しでも上げるための簡単な手段を一つ紹介。
WordPress用のコードも載せてみます。では。結論が欲しいひとは一番下までワープしましょう。
DNS prefetch というのがそれ
DNS を先読みさせる仕組みのこと。
DNS については Wikipedia を見ればいいと思うよ。
DNS prefetch での効果はというとですね、(引用元: MOZILLA DEVELOPER NETWORK: DNS プリフェッチの制御
DNS による名前解決に必要な帯域幅は小さなものですが、それにかかる時間は非常に大きく、特にモバイル環境では顕著なものとなります。予め名前解決を行っておくことで、例えばユーザーがリンクをクリックした際に、ページが表示されるまでの待ち時間を大きく削減することができ、場合によっては秒単位の効果が現れる場合もあります。
特にモバイル環境においては、 DNS プリフェッチによりページの読み込みにかかる時間が劇的に改善されます。
例えば、多数の画像が表示されるページにおいて、画像が要求される前に名前解決が行われている場合では読み込み時間が 5% 以上削減されるでしょう。
Firefox ブラウザの Mozilla、曰く、です。
これは実装するしか!(ぼくはずっと実装してます
そんな DNS prefetch の効果を目で見てみようか
挙動がわからないと本当に速くなるのかわかりませんね!
ということで、DNS prefetch を有効にしたものとしなかったもので比べてみます。
サンプルとして Facebook, Twitter, Google+, はてなブックマーク のソーシャルボタンを読み込むだけのペラサイトを作って オン/オフ時の挙動を計測してみます。
計測に使用したサンプル
当サイトトップページをURLに指定したソーシャルボタン4つを表示するだけの html。(見なくてもいいところです
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>デフォルト</title>
</head>
<body>
<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.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<div class="fb-like" data-href="http://hayashikejinan.com" data-layout="button_count" data-action="like" data-show-faces="false" data-share="false"></div>
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://hayashikejinan.com">Tweet</a>
<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>
<div class="g-plusone" data-size="medium" data-href="http://hayashikejinan.com"></div>
<script type="text/javascript">
window.___gcfg = {lang: 'ja'};
(function () {
var po = document.createElement('script');
po.type = 'text/javascript';
po.src = 'https://apis.google.com/js/platform.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
<a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard-balloon" data-hatena-bookmark-lang="ja" data-hatena-bookmark-url="http://hayashikejinan.com" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/[email protected]" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a>
<script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8"></script>
</body>
</html>
計測に使用したサイト
WebPagetest というウェブサイトのパフォーマンス・最適化を計測できるサイトを使用。
- Test Location…Tokyo
- Browser…chrome
で調べました。
計測結果
計測結果その1。
読み込みが速いことが確認できます。
プリフェッチ適用前
プリフェッチ適用後
計測結果その2。
詳細を見てみるとわかりやすいです。
プリフェッチを適用した際、 DNS lookup は事前に行われていることが視覚的に確認できますね!
プリフェッチ適用前
プリフェッチ適用後
DNS prefetch の指定方法
html <header></header>
内(<meta charset=UTF-8" />
の直後が望ましい)に1行
<meta http-equiv="x-dns-prefetch-control" content="on">
これで DNS preftch が有効化されます。
prefetch したいドメインの指定は
<link rel="dns-prefetch" href="//www.example.com">
こういうカタチ、 href のところでスラッシュ2つの後にドメインを記述すればおkです。
まぁ簡単。
WordPress で DNS prefetch を実装するコード(簡単版
header.php に書くのはあれなんで、functions.php に書きましょう。
ヘッダーに関数をフックしてやればオッケーです。
こんな感じで。
/**
* dns prefetch をヘッダーに書き出す関数
*/
function dns_prefetch() {
// DNS prefetch を on にするタグを出力用変数に入れる
$output = '<meta http-equiv="x-dns-prefetch-control" content="on">' . "\n";
// prefetch するドメインを追加していく
$output .= '<link rel="dns-prefetch" href="//connect.facebook.net">' . "\n";
$output .= '<link rel="dns-prefetch" href="//s-static.ak.facebook.com">' . "\n";
$output .= '<link rel="dns-prefetch" href="//static.ak.fbcdn.net">' . "\n";
// ↑これを追加したいドメイン名だけ続ける
// 書き出し
echo $output;
}
// add_action( 'フック名', 'フックする関数名', 優先順位:今回は真っ先に実行したいので 1 を指定 )
add_action( 'wp_head', 'dns_prefetch', 1 );
WordPress で DNS prefetch を実装するコード(推奨
簡単版ではひとつひとつ律儀に追加するわかりやすいコードを書きました。
ただプログラミングとしては若干残念なのでプログラムっぽく書くのが望ましいです。
ということでこれが推奨。
サンプルコードでは各種ソーシャルボタンから呼ばれるドメインを指定しています。
/**
* dns prefetch をヘッダーに書き出す関数
*/
function dns_prefetch() {
// DNS prefetch を on にするタグを出力用変数に入れる
$output = '<meta http-equiv="x-dns-prefetch-control" content="on">' . "\n";
// prefetch するドメインのタグひな形
$html = '<link rel="dns-prefetch" href="//%s">' . "\n";
$domains = array(
// facebook
'connect.facebook.net', 's-static.ak.facebook.com', 'static.ak.fbcdn.net', 'static.ak.facebook.com', 'www.facebook.com',
// twitter
'cdn.api.twitter.com', 'p.twitter.com', 'platform.twitter.com', 'twitter.com',
// Google+
'apis.google.com', 'oauth.googleusercontent.com', 'ssl.gstatic.com',
// hatena bookmark
'api.b.st-hatena.com', 'b.hatena.ne.jp', 'b.st-hatena.com', 'cdn-ak.b.st-hatena.com', 'cdn.api.b.hatena.ne.jp',
// pocket
'd7x5nblzs94me.cloudfront.net', 'widgets.getpocket.com',
// pinterest
'assets.pinterest.com',
// WordPress
'stats.wordpress.com', 'i0.wp.com', 'i1.wp.com', 'i2.wp.com', 's0.wp.com',
// adsense
'googleads.g.doubleclick.net', 'pagead2.googlesyndication.com',
// analytics
'www.google-analytics.com'
// 追加する場合 ↓ 先頭の // を消して書き込む
//'', '', '', '', '', '', ''
);
// 上記 $domains 配列に入れたドメインをひな形 $html に入れ込み、ループで出力用変数に入れる
foreach ( $domains as $domain ) {
$output .= sprintf( $html, $domain );
}
// 書き出し
echo $output;
}
// add_action( 'フック名', 'フックする関数名', 優先順位:今回は真っ先に実行したいので 1 を指定 )
add_action( 'wp_head', 'dns_prefetch', 1 );
最後に、 DNS prefetch の対応状況
残念ながら Internet Explorer は 10以降の対応です…残念ながら…
他のブラウザはよっぽど古いバージョンで無い限り対応してます。
ホホまとめ
一番の高速化は良い速いサーバーを使うのが最善。
とはいえ簡単なことでサイトの表示速度が上がるとうれしいですよねほんと。
知識+環境で一つ上のサイト作りを目指したいところです。