<< back to list

YSlowでRailsサイトのパフォーマンスを改善する方法 あとで読む

YSlowの記事の続きです。

実際に何らかのサイトにチューニングをかける手順と共に紹介した方が分かりやすいと思うので、このサイトを使ってチューニングしようと思います。
ちなみにApache2.x+mod_railsを使ってRailsを動かしているので、そこを念頭に置いたチューニングをかけていきます。

まず、いきなり否定的な話になりますが、全ての項目でAを取るのはかなり困難です。
たとえば、チェック項目2つ目の「Use a CDN」は、最低でも2つのサーバーを必要としますので、先立つものがないと難しいですし、ほとんどのチェック項目ではAPIなど、自分の管理下にないサーバーを使っている場合、手の出しようがない状態になります。
ですので、今回のチューニングは若干消極的ではありますが「Fの項目を少しでもなくす」を目標にしたいと思います。

1. Make fewer HTTP requests

HTTPリクエストが増える、というのは具体的にどういう状況でしょうか。
例えば、(今時ほぼ存在しないとは思いますが)画像もCSSもJavascriptも使っていない、ただ1つのHTMLからできているページであれば、HTTPリクエストの数は1つです。

ですが、多くのページは1つのHTML上で複数の画像やCSS、Javascriptを読み込みますので、その数だけHTTPリクエストが増える事になります。

では、これらを解決していく方法を考えていきましょう。

FLAMEはSEO的な観点から見てもあまりよろしくない方法ですので、単純に1つのファイルにまとめてしまえば良いでしょう。
次に画像ですが、例えばメニュー画像で「通常状態」と「オンマウス状態」を違う画像を用いて表示している場合は1つにまとめてしまう等、画像ファイルそのものの数を減らしてしまう方法があります(CSS Sprites)。

簡単に説明すると、
オンマウスで変わる画像のサンプル
上記のように、「通常状態」と「オンマウス状態」の画像を1つの画像ファイルとして保存しておきます。
で、スタイルシート側で以下のように記述するだけです。

a.submit {
  width: 48px;                                       /* リンクの幅を指定 */
  height: 18px;                                      /* リンクの高さを指定 */
  background: url(../images/comment.gif) no-repeat;  /* 用意した画像のパスを指定します */
  text-indent: -10000px;                             /* aタグの中にあるテキストを消します */
  display: block;                                    /* ブロック要素にすることで、width, heightを使えるようにしている */
}

a.submit:hover { background-position: -48px 0; } /* オンマウス時に、背景が変わるようにしている */

ちなみに、HTML側はこんな感じ。

<a class="submit">SUBMIT</a>

CSSを読み込める環境では、用意したSUBMITボタンが、読み込めない環境では、テキストで「SUBMIT」と表示されます。

ちなみに、「CSS Sprite Generator」というサイトで、このような結合画像とCSSを自動生成してくれるサービスを提供してくれています。自信のない方はこちらを使ってみるのも手かと。

さて、残るはCSSとJavaScriptですが、今回のようにあくまでもRuby on Rails上でのチューニング、ということであれば下記のようにしてしまう、という手があります。

HTMLヘッダの中で、stylesheet_link_tagやjavascript_include_tagを使用する際に、

<%= stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" %>

と、「:cache=>"キャッシュファイル名"」を追加してしまいます。
通常であれば、上記の実行結果は

<link href="/stylesheets/shop.css"  media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/cart.css" media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/checkout.css" media="screen" rel="stylesheet" type="text/css" />

と、3つのファイルに分かれて出力されるはずですが、config/environments/ENVIRONMENT.rb 内の「config.action_controller.perform_caching」がtrueになっていれば、下記のように、1ファイルにまとめて出力されます。

 <link href="/stylesheets/payment.css"  media="screen" rel="stylesheet" type="text/css" />

上記を行う事で、CSSファイルとJavaScriptファイルのリクエスト数を減らす事ができます。

※Railsの初期設定では、production.rbではtrue, それ以外のファイルではfalseになっています。development環境ではCSSもJavaScriptも頻繁に書き換えが発生しますので、特にいじる必要はないでしょう。

2.Use a CDN

この改善案は、同じコンテンツを有するサーバーを最低でも2つ必要としますので、個人のサイトレベルでは荷が重すぎるでしょう。今回は見送りです。

3.Add an Expires header

mod_expireを利用してHTTPレスポンスヘッダにExpires(コンテンツの有効期限)を追加することで、ブラウザーが短期間に同じデータを何度も読みに行かなくなります。

例えば、画像ファイルやCSS、JavaScriptなどは、一度公開してしまえばあまり修正が入ることのない項目です。これらのファイルに対し、「最低○日間はクライアント側のキャッシュを使ってよ」というヘッダを付加しておく事で無駄なリクエスト数を減らそう、という方法です。

実際にはApacheの設定ファイルであるhttpd.confファイルに、下記の修正を加えます。

FileETag none

ExpiresActive On
ExpiresByType text/css "access plus 3 days"
ExpiresByType application/x-javascript "access plus 3 days"
ExpiresByType image/jpeg "access plus 3 days"
ExpiresByType image/png "access plus 3 days"
ExpiresByType image/gif "access plus 3 days"

上記の設定では、クライアントのキャッシュを3日間使用するよう設定しています。
※YSlowのメッセージで、最低3日以上を指定するよう促されたため。ここの値は、好きに変更すると良いでしょう。

4.Gzip components

テキストデータはGzip圧縮して送信した方がデータ量が減るため、高速にページを表示できるようになります。もちろん、zipの圧縮や解凍にサーバーとクライアントのCPUリソースを消費しますが、それを差し置いても、圧縮によるデータ量削減の方が効果的である、という考え方です。

実際には、Apacheの設定ファイルであるhttpd.confファイルに、下記の修正を加えます。
(Apache1.x系だと、設定方法が違うみたいです)

AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-javasc
ript text/css

上記の例では、HTML, plainText, JavaScript, CSSファイルを圧縮するよう指定しています。

5.Put CSS at the top

ブラウザがページを描画する際に、CSSがコンテンツよりも先に読み込まれていれば、描画時間を短縮することができます。

具体的には、HTMLのHEADタグ内でlinkタグを用いてCSSを読み込むなり、styleタグを用いて直接記述するなりすれば良いわけです。
BODYタグ内に直接CSSを書いた方が気軽ですが、なるべくHEADタグ内に。できれば外部ファイルにしてしまった方が、前述のキャッシュも効いてより有効的です。
(ブラウザのバグの問題もあるので、なるべく外部ファイルにしてlinkタグを使用した方が良いです)

6.Put JS at the bottom

ページ読み込み完了時に動作させても構わないJavaScriptは、HEADタグの中でJavaScriptファイルをincludeするよりもBODYタグの終了直前に読み込ませた方が、見た目上ページの読み込みを早く完了させる事が可能です。
ただし、HTML内の要素を書き換える類のJavaScriptなど、ページを読み込む前に実行しておくべきJavaScriptは、従来通りHEADタグの中などに書いておく必要があります。

とはいえ、ここはJavaScriptの中身を理解した上でやらないと各種バグの原因になりかねない上に、オープンソースライブラリなどで対応がされているかどうかは使ってみるまでわからないので、対応が難しい項目でしょう。

7.Avoid CSS expressions

IEのCSS用拡張であるexpressionは、当然ですがIEでしか使えません。JavaScriptやサーバーサイドで処理できないか検討しましょう。また、未検証ですが、expressionは書き方を誤るとブラウザのスクロールをしただけでも呼ばれるそうで、CPU負荷が高くなりがちなのだそうです。
※expressionを使った事はないので、ここの情報はちょっとよく分からないです。

8.Make JS and CSS external

これは3番目のチューニングと関わって来るのですが、単純にHTTPリクエスト数を減らすだけであれば、CSSもJavaScriptも、全てHTMLファイル内に記述してしまえば良いわけです。
ですが、多くのウェブサイトでは数ページから数百ページのコンテンツを持っています。さらに、動的なページの場合、JSやCSSはそのままに、HTMLの中身だけが書き換わる事が多いため、JSやCSSを外部ファイルに分離した上でキャッシュを有効にしておけば、表示にかかる時間を短縮させることができます。

9.Reduce DNS lookups

ホスト名の逆引きにも、それなりの通信コストが発生するため、不必要に多くのドメインに対し通信させない方が表示時間を短縮できます。
例えばリンクのページなどで、他サイトのバナー画像を直接読みに行っている場合がありますが、自サイトのディスクスペースに余裕があるのであれあば、バナー画像を自サイト内に置く事で逆引きを行うホスト数を減らし、表示時間を短縮させる事が可能です。

10.Minify JS

YUI Compressorなど、JavaScriptの最適化ツールを使用してファイルサイズを削減することで、通信時間の削減と実行速度の向上を見込めます。
これは、個人で作成する(多くても百行程度の)JavaScriptファイルに使用するというよりも、むしろprototype.jsをはじめ、多くの有用なJavaScriptライブラリに使用すると、最も効果が望まれるものでしょう。

ちなみにJavaScriptの最適化ツールが具体的に何を行うのかというと、大体以下のような事をやっているみたいです。

・改行やタブ、スペースの削除
・コメントアウト部分の削除
・ローカル変数名の短縮(変数名の重複が起きない範囲で可能な限り)

11.Avoid redirects

当然ですが、ページをリダイレクトさせるとその分リクエスト数が増えるので表示時間が遅くなります。

12.Remove duplicate scripts

同じスクリプトは関数としてまとめるなど、適切なコードリファクタリングを行いましょう。
プロジェクトが長くなったり、様々な要因が重なって担当者が途中で変わったりすると、書かなくて良い同じCSSやJavaScriptが、プロジェクト内(下手をすると同じファイル内)に3つも4つも出てくる事があります。

同じコードが複数あると、ロードすべきファイルの量が増えるだけでなく、プロジェクトとしてもバグの原因になります。コードの重複は百害あって一利なし、です。

13.Configure Etags

ようやく最後のチェック事項です。適切なETagsの設定をするか、よくわからなければ無効にしてしまいましょう。
(3番のチューニングの際に行ったExpiresヘッダをきちんと指定しており、なおかつ2番のチューニングポイントであるCDNを使用していない場合、ETagsは設定しなくても良いみたいです)

3番のチューニングの際に併せて書いてしまっていますが、僕の環境ではApacheの設定ファイル(httpd.conf)に下記のように書いておく事で、この機能を切ってしまっています。

FileETag none

 

以上、長くなりましたが、YSlowの各項目毎のチューニングポイントをできるだけ初心者の方でも分かりやすい形で書いてみたつもりです。
ちなみに、ここが間違っている、みたいなのがありましたらコメントでもトラックバックでも結構ですので教えていただけると有り難いです。

 

このエントリーを書き終わってから気付いたのですが、Webサイトの高速化 フロントエンドのパフォーマンスの重要性 (Yahoo! developer networkより翻訳)という、YSlowのチェック項目の原点になっているYahoo!の中の人が書いたブログを翻訳されている会社さんがありました。
僕のエントリーよりもかなり玄人向けな内容ですので、物足りない方は是非。

あと、上記の原文を元に作られた書籍が翻訳されていました。パフォーマンス改善に興味のある方は是非。
ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

Rails, パフォーマンス改善, mod_rails, Apache, YSlow, CSS Sprite, mod_expire | comments(0) | trackbacks(1)   このエントリーを含むはてなブックマーク Yahoo!ブックマークに登録 livedoor クリップに登録 del.icio.usに登録 Google Bookmarks に追加 この記事をBuzzurlに追加 2008.11.30 Sun 03:05

COMMENTS

name : email : url :  
captcha: simple_captcha.jpg(全て大文字のアルファベットです)
画像中の文字とおなじものを入力してください。
comment: COMMENT

TRACKBACKS

Red-mount - Red-mount
[...] something about red-mount[...]

この記事へのトラックバックURL: http://www.red-mount.com/trackback/8_5c79b0e5199aa70282e69c402693a6f06029ccc8

<< back to list
 

ABOUT ME

tak (Takahito Sezutsu)

コメント、トラックバックはお気軽に!

COMMENTS

  • Versions - Macで使えるGUIベースのSubversionクライアント
    TANIARollins23 (07.23)
  • Rails勉強会@東京第38回 行ってきました
    TamikaTurner (07.04)
  • MacのSkypeでログイン時プルダウンメニューに表示されるSkype名を消す方法
    tak (06.22)
  • 「オリジナルの項目が見つからなかったので、エイリアス“********”は開けません。」と出て、Finderで外付けHDDが開けない時は
    tak (06.22)
  • 「オリジナルの項目が見つからなかったので、エイリアス“********”は開けません。」と出て、Finderで外付けHDDが開けない時は
    ko (06.22)
  • MacのSkypeでログイン時プルダウンメニューに表示されるSkype名を消す方法
    Mac (05.06)
  • クックパッドの裏側を見てきました
    Taylor30CLEVELAND (03.23)
  • MacのSkypeでログイン時プルダウンメニューに表示されるSkype名を消す方法
    tak (03.11)
  • MacのSkypeでログイン時プルダウンメニューに表示されるSkype名を消す方法
    tama (03.11)
  • Mac版ATOK定額制(体験版)を1週間使ってみた
    tak (09.19)
フィードメーター - RED-MOUNT.COM
あわせて読みたいブログパーツ