GTmetrixのスコアを限界まで上げたいならCloudFlareを使おう


## 注意

* 本投稿は、【[GTmetrixのスコアを限界まで上げたいならCloudFlareは使うな - Qiita][before]】の再検証結果について言及しています。
* 本投稿には、[GTmetrix]の評価を上げる方法については何も書かれていません。
* 本投稿の対象読者は、「出来る限りの最適化を全て行い、あとはCDNを導入すれば完璧」なサイトを作ろうとして、[CloudFlare]の導入を考えている方です。
* 私は英語が読めないので、[Google翻訳]に頼っています。このため、誤った解釈をしている点があるかもしれません。その場合、コメントや編集リクエストにて指摘していただければありがたいです。

## 概要

以前、以下の内容を投稿しました。

[GTmetrixのスコアを限界まで上げたいならCloudFlareは使うな - Qiita][before]

当時は、この投稿に挙げた問題点から、[GTmetrix]のスコアにこだわるならば[CloudFlare]の使用は避けたほうが良い、というのが私の出した結論でした。

それから約1年が経過し、[CloudFlare]や[GTmetrix]は大きく変更されました。
それにより私の挙げた問題点は解消され、今や使用したほうが良いという状況にまで変わっています。

本投稿では、2015年9月現在最新の[CloudFlare]及び[GTmetrix]を使用し、[以前の投稿内容][before]について再検討します。

## 実際のスコア

### 計測対象のページについて

* PHPにより動的に生成したHTMLから、JavaScriptファイル1つ、画像ファイル5つを読み込んでいるページです。
* JavaScriptと画像は、適切なHTTPヘッダを追加するためPHPを経由して出力しています。
* CSSはHTMLに含まれています。このため、CSSファイルの結果は存在しません。

### 計測結果について

* プレビュー画像にリンクを貼っています。リンク先はページ全体のキャプチャ画像です。
* 作成中のサイトであるため、[GTmetrix]内のプレビュー画像とURIは伏せています。
* 作成中のサイトであるため、ページのドメインは`www.example.net`、JavaScriptと画像のドメインは`c.example.net`とします。(ヘッダ内に含まれるドメイン名も、これに合わせたものに修正します)
* キャプチャは[Full Page Screen Capture](https://chrome.google.com/webstore/detail/fdpohaocaechififmbbbbbknoalclacl)で撮影しています。

### CloudFlare導入前

#### Page Speed: A(100%)

[![Page Speedの結果のキャプチャ][GTmetrix-PageSpeed.thumbnail.png]][GTmetrix-PageSpeed.png]

100%。Page Speedについては完璧です。

#### YSlow: A(96%)

[![YSlowの結果のキャプチャ][GTmetrix-YSlow.thumbnail.png]][GTmetrix-YSlow.png]

[Use a Content Delivery Network (CDN)]を解決していないためF(40)です。
しかし、それ以外は全てA(100)。CDNが導入できれば、100%になります。

### CloudFlare導入後

#### Page Speed: A(100%)

[![Page Speedの結果のキャプチャ][CloudFlare-GTmetrix-PageSpeed.thumbnail.png]][CloudFlare-GTmetrix-PageSpeed.png]

CloudFlareの設定で、**わざとキャッシュ期限を2時間としています**。
しかし、実際に送信されるExpiresヘッダの値は、サーバから送信している30日のキャッシュ期限でした。
CloudFlare設定ページの項目「Browser Cache Expiration」のHelpにも、以下のようにあります。

> **Note:** You can also increase the cache expiration by specifying a longer cache time on the origin server, or you can set a different Cache Expiration for a specific path or resource using the Page Rules app.

翻訳と私の解釈が正しければ、ここには「オリジンサーバから長いキャッシュ時間を送信すると、キャッシュ期限を上げられる」と書かれています。
このため、[前回][before]エラーとなっていた[GTmetrix]の[Leverage browser caching]は解決されています。

また、以前自動で挿入されていたHTMLが挿入されなくなりました。
これにより、[Minify HTML]も解決されています。

#### YSlow: A(99%)

[![YSlowの結果のキャプチャ][CloudFlare-GTmetrix-YSlow.thumbnail.png]][CloudFlare-GTmetrix-YSlow.png]

以前とは異なり、[サーバから送信されたHTTPヘッダがほぼ維持されている](#cloudflare%E5%B0%8E%E5%85%A5%E5%BE%8C-1)ため、ExpiresヘッダやETagヘッダがほぼそのまま保持されています。
これにより、[前回][before]エラーとなっていた[Add Expires headers]及び[Configure entity tags (ETags)]が解決されています。

[前回][before]同様、[Use cookie-free domains]はエラーとなります。
しかし、本命である[Use a Content Delivery Network (CDN)]は[Use cookie-free domains]より優先度が高いため、結果としてスコアも上がっています!
([Use cookie-free domains]のPRIORITYはLOWなのに対し、[Use a Content Delivery Network (CDN)]はMEDIUMです。)

## CloudFlare導入によるHTTPレスポンスヘッダの変化

※CSSはHTMLに埋め込んでいるため、結果はありません。
※一部のヘッダーに含まれるサイトのドメインは、`www.example.net`及び`c.example.net`に置き換えています。

### CloudFlare導入前

#### HTML

```http
HTTP/1.1 200 OK
Accept-Ranges:bytes
Cache-Control:no-cache, must-revalidate
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:3308
Content-Security-Policy:default-src 'self' c.example.net; style-src 'self' 'unsafe-inline'; script-src 'self' c.example.net; img-src 'self' 'unsafe-inline' c.example.net; report-uri /csp-report
Content-Type:text/html;charset=utf-8
Date:Sat, 05 Sep 2015 18:58:45 GMT
Expires:Mon, 26 Jul 1997 05:00:00 GMT
Keep-Alive:timeout=2, max=20
Last-Modified:Sat, 05 Sep 2015 18:58:46 GMT
pragma:no-cache
Server:Apache
Set-Cookie:c=1; expires=Tue, 05-Sep-2017 06:36:18 GMT; Max-Age=63113852; path=/
Vary:Accept-Encoding
X-Content-Type-Options:nosniff
x-dns-prefetch-control:on
X-Download-Options:noopen
X-Frame-Options:SAMEORIGIN
X-UA-Compatible:IE=edge,chrome=1
X-WebKit-CSP:default-src 'self' c.example.net; style-src 'self' 'unsafe-inline'; script-src 'self' c.example.net; img-src 'self' 'unsafe-inline' c.example.net; report-uri /csp-report
X-XSS-Protection:1; mode=block
```

#### JavaScript

```http
HTTP/1.1 200 OK
Accept-Ranges:bytes
Access-Control-Allow-Origin:*
Cache-Control:public, max-age=2592000
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:21222
Content-Type:application/javascript
Date:Sat, 05 Sep 2015 18:58:46 GMT
Etag:"Ob7qSMYEipoDyD0kPs/jHx5OstD6YrqTH8BNxlIztzur3xupuh9G4qtX2QGidzlQcQsYrT+Ym3jfSt0e6QQ2DA"
Expires:Mon, 05 Oct 2015 18:58:47 GMT
Keep-Alive:timeout=2, max=20
Last-Modified:Sat, 24 Jan 2015 08:07:40 GMT
Server:Apache
Vary:Accept-Encoding
X-Content-Type-Options:nosniff
X-Download-Options:noopen
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
```

#### 画像

```http
HTTP/1.1 200 OK
Accept-Ranges:bytes
Cache-Control:public, max-age=2592000
Connection:Keep-Alive
Content-Length:8307
Content-Type:image/png
Date:Sat, 05 Sep 2015 18:58:46 GMT
Etag:"3i7Gtvyz91OC4yPTJhDPn+uZC6q+JSVl7jT0RxI6tWlpDbW9qJKC4/p+HNSmfVE5YfetgpVFXzvya4+aPXv5EA"
Expires:Mon, 05 Oct 2015 18:58:47 GMT
Keep-Alive:timeout=2, max=20
Last-Modified:Wed, 22 Oct 2014 05:48:16 GMT
Server:Apache
X-Content-Type-Options:nosniff
X-Download-Options:noopen
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
```

### CloudFlare導入後

以前とは異なり、サーバから送信された`X-Content-Type-Options: nosniff`ヘッダ等も維持されています。

#### HTML

```http
HTTP/1.1 200 OK
Cache-Control:no-cache, must-revalidate
CF-RAY:2214475731732096-KIX
Connection:keep-alive
Content-Encoding:gzip
Content-Security-Policy:default-src 'self' c.example.net; style-src 'self' 'unsafe-inline'; script-src 'self' c.example.net; img-src 'self' 'unsafe-inline' c.example.net; report-uri /csp-report
Content-Type:text/html;charset=utf-8
Date:Sat, 05 Sep 2015 19:18:12 GMT
Expires:Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified:Sat, 05 Sep 2015 19:18:12 GMT
pragma:no-cache
Server:cloudflare-nginx
Set-Cookie:c=1; expires=Tue, 05-Sep-2017 06:55:44 GMT; Max-Age=63113852; path=/
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Content-Type-Options:nosniff
x-dns-prefetch-control:on
X-Download-Options:noopen
X-Frame-Options:SAMEORIGIN
X-UA-Compatible:IE=edge,chrome=1
X-WebKit-CSP:default-src 'self' c.example.net; style-src 'self' 'unsafe-inline'; script-src 'self' c.example.net; img-src 'self' 'unsafe-inline' c.example.net; report-uri /csp-report
X-XSS-Protection:1; mode=block
```

#### JavaScript

```http
HTTP/1.1 200 OK
Access-Control-Allow-Origin:*
Cache-Control:public, max-age=2592000
CF-Cache-Status:HIT
CF-RAY:2214475c5143204e-KIX
Connection:keep-alive
Content-Encoding:gzip
Content-Type:application/javascript
Date:Sat, 05 Sep 2015 19:18:13 GMT
Etag:W/"Ob7qSMYEipoDyD0kPs/jHx5OstD6YrqTH8BNxlIztzur3xupuh9G4qtX2QGidzlQcQsYrT+Ym3jfSt0e6QQ2DA"
Expires:Mon, 05 Oct 2015 19:18:13 GMT
Last-Modified:Sat, 24 Jan 2015 08:07:40 GMT
Server:cloudflare-nginx
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Content-Type-Options:nosniff
X-Download-Options:noopen
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
```

#### 画像

```http
HTTP/1.1 200 OK
Accept-Ranges:bytes
Cache-Control:public, max-age=2592000
CF-Cache-Status:HIT
CF-RAY:2214475c5d7e2096-KIX
Connection:keep-alive
Content-Length:8307
Content-Type:image/png
Date:Sat, 05 Sep 2015 19:18:13 GMT
Etag:"3i7Gtvyz91OC4yPTJhDPn+uZC6q+JSVl7jT0RxI6tWlpDbW9qJKC4/p+HNSmfVE5YfetgpVFXzvya4+aPXv5EA"
Expires:Mon, 05 Oct 2015 19:18:13 GMT
Last-Modified:Wed, 22 Oct 2014 05:48:16 GMT
Server:cloudflare-nginx
Vary:Accept-Encoding
X-Content-Type-Options:nosniff
X-Download-Options:noopen
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
```

### 差分

※計測時間の差により、増減していないヘッダも変化しています。

#### HTML

```diff
 HTTP/1.1 200 OK
-Accept-Ranges:bytes
 Cache-Control:no-cache, must-revalidate
+CF-RAY:2214475731732096-KIX
-Connection:Keep-Alive
+Connection:keep-alive
 Content-Encoding:gzip
-Content-Length:3308
 Content-Security-Policy:default-src 'self' c.example.net; style-src 'self' 'unsafe-inline'; script-src 'self' c.example.net; img-src 'self' 'unsafe-inline' c.example.net; report-uri /csp-report
 Content-Type:text/html;charset=utf-8
-Date:Sat, 05 Sep 2015 18:58:45 GMT
+Date:Sat, 05 Sep 2015 19:18:12 GMT
 Expires:Mon, 26 Jul 1997 05:00:00 GMT
-Keep-Alive:timeout=2, max=20
-Last-Modified:Sat, 05 Sep 2015 18:58:46 GMT
+Last-Modified:Sat, 05 Sep 2015 19:18:12 GMT
 pragma:no-cache
-Server:Apache
+Server:cloudflare-nginx
-Set-Cookie:c=1; expires=Tue, 05-Sep-2017 06:36:18 GMT; Max-Age=63113852; path=/
+Set-Cookie:c=1; expires=Tue, 05-Sep-2017 06:55:44 GMT; Max-Age=63113852; path=/
+Transfer-Encoding:chunked
 Vary:Accept-Encoding
 X-Content-Type-Options:nosniff
 x-dns-prefetch-control:on
 X-Download-Options:noopen
 X-Frame-Options:SAMEORIGIN
 X-UA-Compatible:IE=edge,chrome=1
 X-WebKit-CSP:default-src 'self' c.example.net; style-src 'self' 'unsafe-inline'; script-src 'self' c.example.net; img-src 'self' 'unsafe-inline' c.example.net; report-uri /csp-report
 X-XSS-Protection:1; mode=block
```

#### JavaScript

```diff
 HTTP/1.1 200 OK
-Accept-Ranges:bytes
 Access-Control-Allow-Origin:*
 Cache-Control:public, max-age=2592000
+CF-Cache-Status:HIT
+CF-RAY:2214475c5143204e-KIX
-Connection:Keep-Alive
+Connection:keep-alive
 Content-Encoding:gzip
-Content-Length:21222
 Content-Type:application/javascript
-Date:Sat, 05 Sep 2015 18:58:46 GMT
+Date:Sat, 05 Sep 2015 19:18:13 GMT
-Etag:"Ob7qSMYEipoDyD0kPs/jHx5OstD6YrqTH8BNxlIztzur3xupuh9G4qtX2QGidzlQcQsYrT+Ym3jfSt0e6QQ2DA"
+Etag:W/"Ob7qSMYEipoDyD0kPs/jHx5OstD6YrqTH8BNxlIztzur3xupuh9G4qtX2QGidzlQcQsYrT+Ym3jfSt0e6QQ2DA"
-Expires:Mon, 05 Oct 2015 18:58:47 GMT
+Expires:Mon, 05 Oct 2015 19:18:13 GMT
-Keep-Alive:timeout=2, max=20
 Last-Modified:Sat, 24 Jan 2015 08:07:40 GMT
-Server:Apache
+Server:cloudflare-nginx
+Transfer-Encoding:chunked
 Vary:Accept-Encoding
 X-Content-Type-Options:nosniff
 X-Download-Options:noopen
 X-Frame-Options:DENY
 X-XSS-Protection:1; mode=block
```

#### 画像

```diff
 HTTP/1.1 200 OK
 Accept-Ranges:bytes
 Cache-Control:public, max-age=2592000
+CF-Cache-Status:HIT
+CF-RAY:2214475c5d7e2096-KIX
-Connection:Keep-Alive
+Connection:keep-alive
 Content-Length:8307
 Content-Type:image/png
-Date:Sat, 05 Sep 2015 18:58:46 GMT
+Date:Sat, 05 Sep 2015 19:18:13 GMT
 Etag:"3i7Gtvyz91OC4yPTJhDPn+uZC6q+JSVl7jT0RxI6tWlpDbW9qJKC4/p+HNSmfVE5YfetgpVFXzvya4+aPXv5EA"
-Expires:Mon, 05 Oct 2015 18:58:47 GMT
+Expires:Mon, 05 Oct 2015 19:18:13 GMT
-Keep-Alive:timeout=2, max=20
 Last-Modified:Wed, 22 Oct 2014 05:48:16 GMT
-Server:Apache
+Server:cloudflare-nginx
+Vary:Accept-Encoding
 X-Content-Type-Options:nosniff
 X-Download-Options:noopen
 X-Frame-Options:DENY
 X-XSS-Protection:1; mode=block
```

## 結論

HTMLを自前でMinifyしており、
コンテンツも自前でgzip圧縮し、
HTTPヘッダも適切に指定し、
コンテンツをわざわざ別ドメインで配信し、
それによってAA評価を得ている場合は、
さらなる高評価のため[CloudFlare]の導入を考えてください。

別ドメインで配信する労力は無駄になりますが、評価が上昇します。

## 備考

以降は、[GTmetrix]の評価とはあまり関連性のない、[CloudFlare]による影響について記述します。

### CloudFlareの出力にKeep-Aliveヘッダが無い

[差分]をみると分かるように、いずれのレスポンスからもKeep-Aliveヘッダが無くなっています。
これによる影響について調べた所、HTTP 1.1ではConnectionヘッダで明示されない限り自動でkeep-alive(TCP接続の再利用)が行われるので、このヘッダが無くても問題はないようです。

[キープアライブ - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%BC%E3%83%97%E3%82%A2%E3%83%A9%E3%82%A4%E3%83%96#HTTP.E3.82.AD.E3.83.BC.E3.83.97.E3.82.A2.E3.83.A9.E3.82.A4.E3.83.96)

<blockquote cite="https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%BC%E3%83%97%E3%82%A2%E3%83%A9%E3%82%A4%E3%83%96#HTTP.E3.82.AD.E3.83.BC.E3.83.97.E3.82.A2.E3.83.A9.E3.82.A4.E3.83.96"><p>この機能は、HTTP 1.0では"Connection: Keep-alive"ヘッダを入れることで有効になったが、HTTP 1.1ではデフォルトで有効になっている</p></blockquote>

[【HTTP】Keep Alive のメモ at softelメモ](https://www.softel.co.jp/blogs/tech/archives/2490)

<blockquote cite="https://www.softel.co.jp/blogs/tech/archives/2490"><p>HTTP 1.1 では、すべての接続がkeep-alive。</p><p>次のようなヘッダが送信されない限りは keep-alive。</p><pre>Connection: close</pre><p>なので、<code>Connection: Keep-Alive</code> のヘッダはもう意味がない。</p></blockquote>

また、**Keep-Aliveヘッダは無い方が良い**という情報も見つけました。

[【HTTP】Keep Alive のメモ at softelメモ](https://www.softel.co.jp/blogs/tech/archives/2490)

<blockquote cite="https://www.softel.co.jp/blogs/tech/archives/2490"><p><code>Keep-Alive: </code> というオプションのヘッダが RFC2068 にあるが、きちんと定義されておらず、ほとんど意味がない。使用を避けるべし。</p></blockquote>

このため、CloudFlareによるKeep-Aliveヘッダの削除は有用と言えるでしょう。

### CloudFlareの出力からContent-Lengthヘッダが消え、HTTP Chunked transfer encodingに変わっている

[差分]をみると分かるように、HTMLとJavaScriptのレスポンスからContent-Lengthヘッダが消え、Transfer-Encodingヘッダが追加されたHTTP Chunked transfer encodingによる送信に変わってしまっています。
HTTP Chunked transfer encodingはストリーミング等の特殊な用途以外では、利用しないほうが良いものです。

[HTTP Chunked transfer encodingの各チャンクサイズの決定方法は?(3950)｜teratail](https://teratail.com/questions/3950#r5447)

<blockquote cite="https://teratail.com/questions/3950#r5447"><p><code>Content-Length:&nbsp;xxx</code>&nbsp;の計算が容易なため、（TCPレベルで見たときの）通信が1回で済むこちらを使うべきでしょう。&nbsp;<code>Transfer-Encoding:&nbsp;Chunked</code>&nbsp;の出る幕はありません。</p></blockquote>

[PHP での HTTP レスポンスを Transfer-Enconding: Chunked から Content-Length 指定に変えたい - tilfin's note](http://tilfin.hatenablog.com/entry/20080723/1216791007)

<blockquote cite="http://tilfin.hatenablog.com/entry/20080723/1216791007"><p>そもそもチャンクなのもどうのかなぁと思っていたら、<br> DoCoMo の<a href="http://d.hatena.ne.jp/keyword/i%A5%E2%A1%BC%A5%C9">iモード</a>コンテンツ作成時の仕様 HTTPより<br><a href="http://www.nttdocomo.co.jp/service/imode/make/content/html/notice/basis/#p04">http://www.nttdocomo.co.jp/service/imode/make/content/html/notice/basis/#p04</a></p> <blockquote> <p>CGI作成時に「Content-Type」、「Content-Length」は必須項目となります。</p> </blockquote> <p>とあるので、ケータイからアクセス対応も考えるとチャンクではなく Content-Length で対応しないと駄目ということです。</p></blockquote>

この問題について調べた所、以下のページを見つけました。

[Why is my dynamic content being sent with chunked encoding? – CloudFlare Support](https://support.cloudflare.com/hc/en-us/articles/200168386-Why-is-my-dynamic-content-being-sent-with-chunked-encoding-)

ここによると、[特定の拡張子](https://support.cloudflare.com/hc/en-us/articles/200172516-Which-file-extensions-does-CloudFlare-cache-for-static-content-)のコンテンツのみをCloudFlareはキャッシュし、それ以外はキャッシュせずHTTP Chunked transfer encodingとgzip圧縮で送信するとのこと。
HTMLについては確かに拡張子が未設定なため、これにも合致します。
しかし、JavaScriptはキャッシュされる拡張子を持っているにも関わらず、キャッシュされていません。
解決策についても書かれているようなのですが、適切な翻訳と解釈が出来ないため不明です。

### CloudFlareの出力のEtagヘッダの値が、弱いETag値に変わっている

[差分]をみると分かるように、JavaScriptのレスポンスのEtagヘッダに`W/`が追加され、弱いETag値に変化しています。

[HTTP ETag - Wikipedia](https://ja.wikipedia.org/wiki/HTTP_ETag#.E5.BC.B7.E3.81.84ETag.E5.80.A4.E3.81.A8.E5.BC.B1.E3.81.84ETag.E5.80.A4)

<blockquote cite="https://ja.wikipedia.org/wiki/HTTP_ETag#.E5.BC.B7.E3.81.84ETag.E5.80.A4.E3.81.A8.E5.BC.B1.E3.81.84ETag.E5.80.A4"><p>ETagには<b>強いETag値</b>と<b>弱いETag値</b>が存在する。表記としては、頭に「W/」が付くものが弱いETag値、付かないものが強いETag値である<sup><a href="https://ja.wikipedia.org/wiki/HTTP_ETag#cite_note-ueno_146_147-3">[3]</a></sup>。</p><pre>"123456789"   -- 強いETag値&#x0A;W/"123456789"  -- 弱いETag値</pre><p>強いETag値が一致すれば、2つのリソースが1バイトも変わらず、またContent-Languageなどのヘッダも変わっていないことを示す。強いETagはキャッシュや部分リクエストにも使いうる。</p><p>弱いETag値が一致した場合、2つのリソースは意味合いとして同じ、つまり実用的にはキャッシュされたものを代用できる、ということを示している。ただ、1バイトも変わらず同じであることは保証されず、部分リクエストのバリデーションには使えない。これは、Webページを動的に生成する場合など、強いETagをサーバで生成することが現実的でない場合に使うことができる。</p></blockquote>

恐らく、[CloudFlareの出力からContent-Lengthヘッダが消え、HTTP Chunked transfer encodingに変わっている]でも書いたように、JavaScriptがCloudFlareにキャッシュされていない事が原因であると考えられます。

### CloudFlareの出力にAccept-Rangesヘッダが無い

[差分]をみると分かるように、HTMLとJavaScriptのレスポンスからAccept-Rangesヘッダが消えてしまっています。
Accept-RangesヘッダはRange Requestsに対応している場合に送信するヘッダです。
画像ではAccept-Rangesヘッダが保持されている(あるいは、CloudFlareが追加した)点から、[CloudFlareの出力からContent-Lengthヘッダが消え、HTTP Chunked transfer encodingに変わっている]でも書いたようなCloudFlareにキャッシュされるコンテンツにて追加されるものと考えられます。



[GTmetrix]:http://gtmetrix.com
[CloudFlare]:https://www.cloudflare.com
[Google翻訳]:https://translate.google.co.jp/?hl=ja
[before]:http://qiita.com/sounisi5011/items/99661dc2f65188b43f94

[Use cookie-free domains]:http://gtmetrix.com/use-cookie-free-domains.html
[Use a Content Delivery Network (CDN)]:http://gtmetrix.com/use-a-content-delivery-network-cdn.html
[Add Expires headers]:http://gtmetrix.com/add-expires-headers.html
[Configure entity tags (ETags)]:http://gtmetrix.com/configure-entity-tags-etags.html
[Leverage browser caching]:http://gtmetrix.com/leverage-browser-caching.html
[Minify HTML]:http://gtmetrix.com/minify-html.html

[GTmetrix-PageSpeed.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/dd30e600-6380-84bb-60ac-c1753cad6eb7.png
[GTmetrix-PageSpeed.thumbnail.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/d507293a-619c-3617-decc-66cc33f3d4c3.png
[GTmetrix-YSlow.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/17b07357-5ec9-aaf8-c335-bb0dd4d553c6.png
[GTmetrix-YSlow.thumbnail.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/8816b6d4-1ee6-f400-f92a-c90d2af5b2ab.png
[CloudFlare-GTmetrix-PageSpeed.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/89ca4dea-df1d-2bac-9734-ec49b4047136.png
[CloudFlare-GTmetrix-PageSpeed.thumbnail.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/04bc19e9-ff0a-7850-d8ad-f318977b1d8f.png
[CloudFlare-GTmetrix-YSlow.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/4165a8c9-59fa-c65b-d76f-9381eea69ddf.png
[CloudFlare-GTmetrix-YSlow.thumbnail.png]:https://qiita-image-store.s3.amazonaws.com/0/35948/64c03861-f708-93c7-6bcb-8a0bacab7416.png

[差分]:#%E5%B7%AE%E5%88%86
[CloudFlareの出力からContent-Lengthヘッダが消え、HTTP Chunked transfer encodingに変わっている]:#cloudflare%E3%81%AE%E5%87%BA%E5%8A%9B%E3%81%8B%E3%82%89content-length%E3%83%98%E3%83%83%E3%83%80%E3%81%8C%E6%B6%88%E3%81%88http-chunked-transfer-encoding%E3%81%AB%E5%A4%89%E3%82%8F%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B