Resource Hintsでリソースを事前取得しよう！

#Resource Hintsとは？
下記4つのAPIから構成される。IEについては10以降にはなるが、大体のブラウザでサポートされている。
- DNS-Prefetch
- Preconnect
- Prefetch
- Prerender

詳しくは[Resource Hints](https://w3c.github.io/resource-hints/)参照。

##DNS-Prefetch
ソーシャルボタンの設置やCDNの利用など、外部サイトからリソースを読み込む場合、「DNSルックアップ（ドメインをIPアドレスに変換すること）」が複数発生します。下記のように指定することで、あらかじめドメインの名前解決を行うことが可能です。

```html:html
<link rel="dns-prefetch" href="//example.com">
```

###参考
DNSプリフェッチにより実際に高速化された例など、下記サイトにかなり詳しく書いてあります。
[ソーシャルメディアの読み込みはDNSプリフェッチのまとめ設定がお得 | ゆっくりと…](http://tokkono.cute.coocan.jp/blog/slow/index.php/programming/boostup-socials-with-dns-prefetch/)

&lt;head&gt;内でまとめて設定しておくと良いと思います（下記scriptは参考サイト参照）。

```js:js
(function(document) {
    var servers = [
        /* evernote */
        "static.evernote.com"
 
        /* pocket */
        ,"d7x5nblzs94me.cloudfront.net"
        ,"widgets.getpocket.com"
 
        /* mixi */
        ,"img.mixi.net"
        ,"static.mixi.jp"
        ,"plugins.mixi.jp"
 
        /* google analytics, google +1 */
        ,"oauth.googleusercontent.com"
        ,"ssl.gstatic.com"
        ,"accounts.google.com"
        ,"apis.google.com"
        ,"www.google-analytics.com"
 
        /* facebook */
        ,"www.facebook.com"
        ,"s-static.ak.facebook.com"
        ,"static.ak.fbcdn.net"
        ,"static.ak.facebook.com"
        ,"connect.facebook.net"
 
        /* twitter */
        ,"twitter.com"
        ,"cdn.api.twitter.com"
        ,"p.twitter.com"
        ,"platform.twitter.com"
 
        /* hatena */
        ,"cdn-ak.b.st-hatena.com"
        ,"cdn.api.b.hatena.ne.jp"
        ,"b.st-hatena.com"
 
        /* zenback */
        ,"web-jp.ad-v.jp"
        ,"w.zenback.jp"
    ], i, e, link = document.createDocumentFragment();
 
    for (i = servers.length-1; i >= 0; i--) {
        e = document.createElement('link');
        e.setAttribute('rel', 'dns-prefetch');
        e.setAttribute('href', '//' + servers[i]);
        link.appendChild(e);
    }
 
    document.getElementsByTagName('head')[0].appendChild(link);
}(document));
```

##Preconnect
DNSの名前解決に加え、TCPコネクションまで貼っておく。

```html:html
<link rel="preconnect" href="//example.com">
<link rel="preconnect" href="//cdn.example.com" crossorigin>
```

##Prefetch
あらかじめ取得したいリソースが静的にアクセス可能な場合、Prefetchを使うことでキャッシュに格納させ、リソースの読み込みを高速にします。

```html:html
<link rel="prefetch" href="//example.com/next-page.html" as="html" crossorigin="use-credentials">
<link rel="prefetch" href="/library.js" as="script">
```

##Prerender
linkタグのrel属性でURLを指定することで、Webページを事前に読み込ませ、次ページを高速に表示します。

```html:html
<link rel="prerender" href="//example.com/next-page.html">
```
※ちなみに1ページしか指定できません

###確認方法について
Chromeの開発者ツールが開いていると動作しないので閉じます。
事前レンダリングが実際に行われているかは、Chromeで「chrome://net-internals/#prerender」と打つことで確認が可能。

[事前レンダリング DEMO](https://andus.heteml.jp/demo/prerender/)
※画像はキャッシュされないようにしています

![pre1.png](https://qiita-image-store.s3.amazonaws.com/0/95865/79072df1-0a46-ac07-524a-882e84e46030.png)

また、Chromeのメニューから「その他のツール」→「タスク マネージャ」でも確認ができます。

![pre2.png](https://qiita-image-store.s3.amazonaws.com/0/95865/b017701d-3c23-1d38-59dd-47f2662955bd.png)

##どんなケースで使えるの？
ユーザーが次に移動すると考えられるページURLを指定すると良い。
・フォームの入力画面→確認画面
・ブログの一覧・詳細→トップページ
などなど。バックグラウンドで事前取得するとは言え、**JavaScriptを実行する訳ではないので、Googleアナリティクスで開いていない次ページをPV計上、などはされない**ので安心。

##デメリットは？
・バックグラウンド（別タブ）で処理しているため、ネットワーク帯域を消費する。
・読み込み時にアニメーションするようなページの場合、開くとアニメーションが終わっている可能性がある。
・スマホユーザーのデータ使用量を無駄に消費する可能性がある。

##大手の事例
ここで終わってもつまらないので、大手サイトの利用例を見てみましょう。

```html:Twitter
<link rel="dns-prefetch" href="https://pbs.twimg.com">
<link rel="dns-prefetch" href="https://t.co">
<link rel="preload" href="https://abs.twimg.com/k/ja/init.ja.640d0656a56931310909.js" as="script">
<link rel="preload" href="https://abs.twimg.com/k/ja/16.commons.ja.747d52f46f99a6a58506.js" as="script">
<link rel="preload" href="https://abs.twimg.com/k/ja/7.pages_home.ja.6c89e737b2894bdc15cd.js" as="script">
```

```html:Facebook
<link rel="preload" href="https://www.facebook.com/rsrc.php/v3/yf/r/JS-dyZdNSwf.css" as="style" crossorigin="anonymous" />
```

```html:Pinterest
<meta http-equiv="x-dns-prefetch-control" content="on">
```

```html:Amazon
<meta http-equiv='x-dns-prefetch-control' content='on'>
<link rel='dns-prefetch' href='//images-fe.ssl-images-amazon.com'>
<link rel='dns-prefetch' href='//m.media-amazon.com'>
<link rel='dns-prefetch' href='//completion.amazon.com'>
```

```html:AWS
<link rel="dns-prefetch" href="https://a0.awsstatic.com" />
<link rel="dns-prefetch" href="//d0.awsstatic.com" />
<link rel="dns-prefetch" href="//d1.awsstatic.com" />
```

DNS-Prefetchは各社よく使っていますね。&lt;meta http-equiv='x-dns-prefetch-control' content='on'&gt;はブラウザにDNS Preftchを有効化させる指定です。

Prerenderについては、Googleでサイト名を検索した時くらいしか見つけられませんでした。大体の場合で指定したサイトが一位に表示され、そのサイトを事前レンダリングしておくのは理にかなっていることと思います。
![cap3.png](https://qiita-image-store.s3.amazonaws.com/0/95865/838016dd-8ffa-f719-e0f6-8061c6444e28.png)
###参考リンク
[プリレンダリングとプリフェッチのサポート (Windows)](https://msdn.microsoft.com/ja-jp/library/dn265039%28v=vs.85%29.aspx)
[resouce hintsとpreloadを使ってリソースの取得を最適化する | 69log](https://blog.kazu69.net/2016/03/19/optimize_resources_using_resoucehint_and_preload/)