アプリケーションエンジニアができるフロントエンドの改善

## はじめに

半年前に読んだ[ハイパフォーマンスWebサイト](http://www.amazon.co.jp/%E3%83%8F%E3%82%A4%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9Web%E3%82%B5%E3%82%A4%E3%83%88-%E2%80%95%E9%AB%98%E9%80%9F%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B14%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB-Steve-Souders/dp/487311361X?ie=UTF8&keywords=%E3%83%8F%E3%82%A4%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9&qid=1461460074&ref_=sr_1_2&sr=8-2)を(途中まで)読み直したので、そのまとめを。

開発に関わっている転職サイト[Green](https://www.green-japan.com/)の全体的な速度改善を目的に読みました。
私はスタイルシートなどのデザイン領域だと全然わからず手に負えないので、それ以外のHTTPとかサーバの設定でできることをという感じです。
メモ書き程度なので、読みにくくてもご容赦ください。

## 改善するために
- どこで待ちが長じているかを知るのがまずはじめ
  - New Relicとかツールを使うのがいいのかな
  - 現状のパフォーマンスのプロファイルを取り、どこを改善すれば最も効果があがりのかを突き止める
- フロントエンドの性能向上対策は主に以下の3つがメイン
  - ウェブサイトの設定ファイルを変更する(Expiersヘッダやgzip圧縮の設定など)
  - スクリプトとスタイルシートをページ内の特定の(最適な)場所への配置
  - 画像、スクリプト、スタイルシートを結合すること

## Keep-Aliveやパイプラインといった持続接続
- Keep-Alive(HTTP/1.0)
  - ブラウザが1回の接続で複数のリクエストを送信する事が可能になった
  - connectionヘッダを使ってKeep-Aliveをサポートしている事を知らせることが必要  (HTTP/1.1からは必要なくなった)
- パイプライン(HTTP/1.1)
  - 同一ソケット上で**レスポンスを待たずに**複数のリクエストが送信可能  →Keep-Aliveより高パフォーマンス
  - 古いブラウザはサポートしていない事もあるので、その場合はKeep-Aliveを利用
HTTPSを使う場合はこれらの技術を使う事がいっそう重要となってくる

## コンテンツをユーザの近くに置いておく=CDNの利用
- コンポーネントWebサーバがユーザに近いところにあれば、多数のHTTPリクエストのレスポンスが改善できる
  - レスポンス速度は物理的なサーバとの距離も一定影響があるため
  - コンポーネントウェブサーバは分散させたほうがいい  →CNDサービスを利用


### CDNって？
- CDN(Contents Delivery Netwerk)とは、ユーザにコンテンツをより効率的に配信するために、複数の拠点に分散して配置したウェブサーバの集合
  - 性能を最適化する場合、ある特定のユーザに対してどのサーバからコンテンツを配信するかは、ネットワーク近接性の尺度に基づいて選択される
  - つまり、ユーザのいる場所/距離によって決めるということかな？Greenの場合だったら、現在ユーザの大半は日本にいるので、CDNも日本に設置するのがいいみたいな
### CDNのメリット/デメリット
- メリット
  - レスポンス改善(←今回のメイン)
  - バックアップ
  - ストレージ容量の拡張
  - キャッシュの保持  

→ネットワークトラフィックの一時的な急増による影響を吸収できる

- デメリット
  - 他のウェブサイトのトラフィックの影響を受けることがある  →2種類のCDNサービスを利用すれば回避可能
  - コンテンツサーバを直接管理できない
- CDNの効果は複数の場所から応答時間を計測する必要がある
  - [Keynote Systems](http://jp.keynote.com/)
  - [Gomez](http://www.gomez.co.jp/)
  - って書いてあったけど、他にもいろいろないい方法あると思う


## コンポーネントを圧縮する
- 圧縮できるとレスポンスサイズが小さくなり、サーバからクライアントに送られるパケット数が減るので、転送時間が短縮される
- gzipが最も普及(多くのブラウザがサポート)していて効果的  (この本古いから今だと他の技術もあるかも)

### 圧縮するときの注意点
- HTMLドキュメントだけでなく、スクリプトやスタイルシートまで圧縮すると効果的
- 画像やPDFファイルにはすでに圧縮がかかっているので、圧縮しない
　　- 圧縮すると、圧縮するとき(サーバ側)や展開するとき(クライアント側)に余計なパワーがかかる
- gzipで圧縮しても、その圧縮を理解できないクライアントには送らない
- gzipで圧縮したことを宣言し忘れたレスポンスを送らない

## コンポーネントの再利用
- サイトのすべてのページが同じJavaScriptとCSSを使用しているなら外部ファイルにする事で、コンポーネントの再利用率は高くなる
  - ユーザがページ間を行き来する際にJavaScriptとCSSのコンポーネントがすでにブラウザのキャッシュに入っているので有効になる

## DNSルックアップを減らす
- DNSとはDomain Name Systemのこと
- ホスト名(URL)とIPアドレスを紐付ける役割
- DNSは複数のIPアドレスを１つのポスト名に関連付けられるため、ウェブサイトの高度な冗長性を持たせる事が可能

### DNSのコストを下げる
- ブラウザがホスト名→IPアドレスとするのに20~120msかかる  →これが終わるまで何もダウンロードできない
- 応答時間 = DNSリゾルバ + リゾルバに対するリクエストの負荷 + リゾルバとの(物理的な)距離 + 接続速度
  - DNSリゾルバとはISPの中に含まれているらしい
- DNSをキャッシュさせることが性能向上につながる
  - ブラウザキャッシュとOSのDNSキャッシュの両方にキャッシュさせる
  - ブラウザのキャッシュ→OSのDNSキャッシュの順に利用
  - つまり、1度接続すればPCがアドレスを覚えるので、両方のキャッシュが消えるまではDNSの問い合わせをしなくていい

### TTL
- TTL(Time-To-Level)とは、どれだけの期間DNSのレコードを保持(キャッシュ)できるかをクライアントに通知するもの
- サーバ側は指定する権利を持つ
- 1分~1日で設定
  - DNSリゾルバが即座にアドレスを変更する事が必要な場合は短く設定  →つまり、複数のサーバやコロケーションある場合、仮想IPアドレスを利用している場合は短い
  - GoogleやYahoo、Amazonなどの大手は1~5分で設定しているよう

### DNSルックアップの回数を削減するために
- (ブラウザもOSも)キャッシュが空のとき、問い合わせ回数はウェブページ内の一意なホスト名の数と同じ
  - つまり、一意なホスト名を減らせばDNSの問い合わせ回数も減る
  - DNSの問い合わせ回数が減れば、応答にかかる時間も減る
  - ページ内で実行される並列ダウンロードの回数が減る事もある(←これは時間がかかるのでネガティブな現象)
- コンポーネントは2つ以上、4つ以下のホスト名に分けるのがベスト
  - DNS問い合わせ回数は減らしつつ、並列ダウンロードを十分に活用できる

## まとめ
半年前に読んだときよりはるかに理解が深まり、まだまだいろいろな対策が打てそうだったので、実際にどういう設定をするのがGreenにとって最適化を考えながらレスポンス改善していきたいと思いました。
あと1/3ぐらい残っているので、また追加編集or投稿するかもです。