htmlcss ページの表示速度を改善する方法

2013年6月17日

ページの表示速度を改善する方法について調べたことのメモ。

gzip 圧縮での高速化

自分でファイルを圧縮する方法とサーバーでファイルを圧縮する方法の2通りある。

ファイルを gzip 圧縮して .htaccess で圧縮ファイルを読み込む指定をする

  • 静的なウェブのあまり変更のないファイルに対して向いている。
  • Windows でファイルを圧縮するには、専用のソフトを使うか、CSS や JavaScript を圧縮するなら次のページで可能。Online JavaScript/CSS Compression Using YUI Compressor
  • 圧縮すると、ファイルの拡張子は「.gz」になるのでこれをサーバーにアップロード。
  • 例えば、「base.css」を圧縮すると「base.css.gz」になり、サーバー上には「base.css」と「base.css.gz」の2種類のファイルがある。
  • 以下を「.htaccess」に記述する。(JavaScript と CSS は可能であれば圧縮されたファイルを使うように指定。)gz ファイルが存在する場合にはアクセスされたファイル名.gzを読み込むようにする。
    RewriteEngine On   "# 書き換えエンジンを有効に"
    RewriteCond %{HTTP:Accept-Encoding} gzip  "# gzipが許容されていれば"
    RewriteCond %{REQUEST_FILENAME} !\.gz$  "# 拡張子が「.gz」でなければ次へ"
    RewriteCond %{REQUEST_FILENAME}\.gz -s  "# 元のファイルの末尾に「.gz」を付与したファイルが存在すれば次へ"
    RewriteCond %{REQUEST_FILENAME} \.js$ [OR]  "# JavaScript ファイルまたは"
    RewriteCond %{REQUEST_FILENAME} \.css$  "# CSS ファイルの場合"
    RewriteRule .+ %{REQUEST_URI}.gz  "# URIの末尾に「.gz」を付与"
    
    <FilesMatch "\.js\.gz$">  "# FileMatchでファイル毎に MIME-TYPE と gz エンコードを指定"
        ForceType application/x-javascript
        AddEncoding x-gzip .gz  
    </FilesMatch>
    
    <FilesMatch "\.css\.gz$">
        ForceType text/css
        AddEncoding x-gzip .gz
    </FilesMatch>
  • 圧縮ファイルを利用する場合、HTMLタグ(link, script 要素)の変更は必要ない。
  • 但し、PHP などで動的にファイルが生成される場合、前もってファイルを gzip で圧縮できないので、次の「mod_deflate」を利用する。

mod_deflate の利用

mod_deflate はサーバー側でコンテンツ圧縮を行うための機能で、リクエストされる各ファイルの容量を圧縮することで転送量を減らす方法。但し、サーバーで gzip 圧縮を行うため圧縮コストがかかる(サーバのCPU消費率が高くなる)。また、使用しているサーバーが「mod_deflate」をサポートしている必要がある。

  • 以下を「.htaccess」に記述する。(text, html, xml, css, javascript を圧縮して転送する)
    # AddOutputFilterByType を使用する方法
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
    </IfModule>
  • 「mod_deflate」が機能しているかどうかを調べるには、以下のサイトにアクセスして、「Enter a URL to Test」と言うところに、自分の URL を入力して「Test」をクリックすると、機能しているかどうかが表示される。
    http://www.whatsmyip.org/http-compression-test/
  • また、ホスティングによっては「Optimize Website」というオプションが管理画面(cPanel)にあり、そこで「mod_deflate」の機能を有効にすることができる。

mod_deflate を利用する場合の .htaccess の記述(2)

レンタルサーバによっては「AddOutputFilterByType」を使用できない場合もある。.htaccess ファイルへの記述は「AddOutputFilterByType」のほかに以下のようにも記述できる。画像(gif,jpg,png,ico)以外全て圧縮する場合。

<IfModule mod_deflate.c>
SetOutputFilter DEFLATE

BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary

Header append Vary User-Agent env=!dont-vary
</IfModule>
  • ブラウザによっては、すべてのコンテンツに対する 圧縮を扱えるわけではないので、 BrowserMatch ディレクティブを使用して、特定のブラウザに圧縮が行なわれないようにしたり、html ファイルに対してのみ 圧縮が働くようにしたりしている。
  • 詳細は「Apache モジュール mod_deflate」参照。

ファイルをブラウザにキャッシュさせる

キャッシュを制御する HTTP ヘッダ(Expires ヘッダ)を追加して、リソースをブラウザにキャッシュさせ、httpリクエスト の数を減らす方法。.htaccess にキャッシュの期限を指定する。

サーバーが「mod_expires」をサポートしていれば、有効にして画像ファイルや CSS などの静的ファイルをブラウザにキャッシュさせるように以下を記述する。

更新情報2013年9月26日
JavaScript ファイルの指定の記述を変更。関連情報「ExpiresByType が JavaScript に対して効かない?

<ifModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 30 minutes"
ExpiresByType text/html "access plus 10 seconds"
ExpiresByType image/jpg "access plus 7 days"
ExpiresByType image/jpeg "access plus 7 days"
ExpiresByType image/gif "access plus 7 days"
ExpiresByType image/png "access plus 7 days"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
</ifModule>

上記の例では以下のように設定している。

  • デフォルトは30分
  • HTML ファイルは10秒
  • gif, jpg, png 等の画像ファイルは7日
  • CSS, JavaScript, PDF等は1ヶ月
  • サイトの運用に合わせて変更する必要がある
  • mod_expires の詳細は「Apache モジュール mod_expires」を参照。

注意する点としては、キャッシュの有効期間として指定した期間内はブラウザはローカルのキャッシュを見にいくので、キャッシュ対象にしたファイルや画像などに何等かの変更を加えた場合はファイル名を変更しないと、変更が反映されないこと。ファイル名を変更したくない場合は、以下のような対策がある。

キャッシュの制御

ファイルを更新してもキャッシュの内容が適用されるのを回避するには、更新したファイルのファイル名の末尾に「?xxxxx(任意の文字列)」のような、クエリー文字列を付加することでブラウザはそのクエリー文字列付きの URL を取得していないと判定し、キャッシュから読み込まずに、サーバのファイルを取得する。

この方法は CSS や JavaScript ファイル以外でも有効で、このようにすることで末尾の文字列が変わるたびにブラウザは新しいファイルと認識するため、キャッシュを防ぐことができる。

以下は例。

<link rel="stylesheet" href="../css/style.css?20130617" type="text/css" /> 

<link rel="stylesheet" href="<?php echo get_stylesheet_uri(); ?>?ver=20130617" type="text/css" /> 

<img src="images/foo.jpg?20130617" alt="" />

以下は WordPress のfunctions.php での JavaScript の読み込みの例。

function add_my_scripts() {  
  if(is_admin()) return; 
  wp_enqueue_script('jquery'); //WordPress内蔵の jQuery をロード(省略可能)  
  wp_enqueue_script('base', //「base.js」をロード
    get_template_directory_uri(). '/js/base.js',
    array('jquery'),
    '20130617'  //クエリー文字列を付加
  );
}
add_action('wp_print_scripts', 'add_my_scripts');

以下のように header 内に出力される。

<script src="http://www.xxxxx.com/wp-content/themes/theme_name/js/base.js?ver=20130617" type="text/javascript">