SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

CodeZineニュース

[PHPプロ!] JavaScriptの読み込みを<script src="a.js,b.js,c.js">と記述するハック

  • このエントリーをはてなブックマークに追加

  • このエントリーをはてなブックマークに追加

Patrick Hunlock氏のブログにて、複数ファイルに分かれたJavaScriptを1つにまとめる方法が解説されています。このスクリプトはPHPを使っているため、自前でキャッシュ制御を行うことで、ブラウザのキャッシュ問題に対応したり、ファイルに変更を加えたときにも自動的にキャッシュが再作成されるようになっています。

 Patrick Hunlock氏のブログにて、複数ファイルに分かれたJavaScriptを1つにまとめる方法が解説されています。このスクリプトはPHPを使っているため、自前でキャッシュ制御を行うことで、ブラウザのキャッシュ問題に対応したり、ファイルに変更を加えたときにも自動的にキャッシュが再作成されるようになっています。

 以下、記事の概要を紹介します。

 いろいろなJavaScriptライブラリを使っていると、以下のようなコードになることがあります。

<script src = "yahoo.js" ></script>
<script src = "dom.js" ></script>
<script src = "event.js" ></script>
<script src = "dragdrop.js" ></script>
<script src = "slider.js" ></script>

 これを、以下のようにして読み込めるようにするのが、今回紹介するスクリプトの内容です。

<script src = "scripts/yahoo.js, dom.js, event.js, dragdrop.js, slider.js">
</script>

 動作をするためにはApache WebサーバーとPHPが必要です。まず、.htaccessを編集し、以下のように記述します。

<FilesMatch "^scripts$">
   ForceType application/x-httpd-php 
</FilesMatch>

 これで、/scriptsからはじまるアクセスがあった時には、「scripts」というファイル名のPHPスクリプトが実行されるようになります。scriptsがディレクトリだったり、scripts.phpというファイル名にならないことに注意してください。

 次に、scriptsファイルを作成します。Apacheのドキュメントルートにて、scriptsというファイルを作り、以下のコードを入力します。

<?php
   // このスクリプトはPUBLIC DOMAIN形式ですので、
   // 自由にお使いいただけます
 
   // gzipを重複して使用しないように  
   // zlibエクステンションを停止する 
   ini_set("zlib.output_compression", "Off");
 
   // Content-Typeヘッダーをセットする
   header("Content-Type: text/javascript; charset=UTF-8"); 
 
   // cache-controlヘッダーをセットする
   // HTTP 1.1 ブラウザーは、必ずrevalidateにセット
   header("Cache-Control: must-revalidate");     
 
   // ファイル名の一覧を取り出す
   // URLから/をもとに分解
   $expl = explode("/",$HTTP_SERVER_VARS["REQUEST_URI"]);
   // URLデコードを行い、%20をスペースに変換
   $fileList = trim(urldecode($expl[count($expl)-1]));
   // 残りの文字列に対し、,文字で分解
   $fileNames = explode(",",$fileList);
 
   // $fileNamesに、ファイル名の一覧が配列で格納される
 
   // last-modifierヘッダーを送信するため、
   // 各ファイルを検査し、最終更新日を取り出す
   $newestFile = 0;
   $longFilename = '';
   for ($i=0; ($i < count($fileNames)); $i++) {
      $fileNames[$i] = trim($fileNames[$i]);
      $longFilename .= $fileNames[$i];
      $lastMod = @filemtime($fileNames[$i]);
      if ($lastMod > $newestFile) {
         $newestFile = $lastMod;
      } 
   }
 
//////////////////////////////////////////////////
// ブラウザのキャッシュ制御を行う
 
   $fileHash = md5($longFilename);
   $hash = $fileHash . '-'.$newestFile;
   $headers = getallheaders();
   if (ereg($hash, $headers['If-None-Match']))  {
      header('Last-Modified: '.gmdate('D, d M Y H:i:s',
 $newestFile).' GMT', true, 304);
      die();
   }
 
   header("ETag: \"{$hash}\"");
 
   if (isset($headers['If-Modified-Since'])) {
      if ($newestFile <= strtotime($headers['If-Modified-Since'])) {
         // No change so send a 304 header and terminate
          header('Last-Modified: '.gmdate('D, d M Y H:i:s',
 $newestFile).' GMT', true, 304);
          die();
       }
   }
 
   header('Last-Modified: '.gmdate('D, d M Y H:i:s',
 $newestFile).' GMT');
 
//////////////////////////////////////////////////
 
 
//////////////////////////////////////////////////
// ファイルシステムのキャッシュ制御を行う
 
   $fp = @fopen("cache/$fileHash.txt","r");
   if ($fp) {
      if ($newestFile>@filemtime("cache/$fileHash.txt")) {
         fclose($fp); $fp=false;}
   }
   if (!$fp) {
      $buffer='';
      for ($i=0; ($i < count($fileNames)); $i++) {
         $buffer .= @file_get_contents($fileNames[$i]) . "\n\n";
      }
      $fp = @fopen("cache/$fileHash.txt","w");
      @fwrite($fp,$buffer);
      @fclose($fp);
      $fp = @fopen("cache/$fileHash.gz","w");
      $buffer = gzencode($buffer, 9, FORCE_GZIP);
      @fwrite($fp,$buffer);
      @fclose($fp);
   }
 
 
//////////////////////////////////////////////////
// 出力を行う 
 
   if (strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
      header ("Content-Encoding: gzip");
      header ("Content-Length: " . filesize("cache/$fileHash.gz"));
      readfile("cache/$fileHash.gz");
   } else {
      header ("Content-Length: " . filesize("cache/$fileHash.txt"));
      readfile("cache/$fileHash.txt");
   }
 
//////////////////////////////////////////////////
 
?>

 最後に、cacheディレクトリを作成します。このディレクトリは、scriptsファイルがあるディレクトリと同じ階層になります。このディレクトリは、scriptsファイルが作成するキャッシュファイルを格納するディレクトリで、ファイル名は連結されたファイル名をMD5化したものに、.txtが付加したもの、あるいは.gzを付加したものとなります。Javascriptファイルに修正が加わっても、自動的にキャッシュファイルは新しい内容に更新されます。

 このスクリプトは簡単に試すことができます。たとえば、以下のように記述するだけで、自動的にfile1.js、file2.js、file3.jsをまとめて、キャッシュに残してくれます。なお、これらのファイルはscriptsディレクトリと同階層に設置します。

<script src = "scripts/file1.js, file2.js, file3.js"></script>

 またscripts/の後ろの順序は、すべてのページで同一にしておきます。そうしないと、キャッシュを作成したときに、別々の名前でファイルが生成されてしまいます。

 より詳しい解説は、筆者のブログのSupercharged Javascriptにて確認してください。(PHPプロ!

関連リンク

関連ニュース

転載元

 PHPプロ!:最新のPHPニュース

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
この記事の著者

PHPプロ!(PHPプロ!)

PHPプロ!」は、アシアル株式会社が運営するPHP開発者のためのポータル&コミュニティサイトです。同サイトでは、PHP最新ニュースや、困ったときのQ&A掲示板、初心者向けのPHP講座、PHP中級者のためのTIPSメーリングリスト、中・上級者向けの技術ノウハウ満載のPHPプロ!マガジンの提供など、PHP開発...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/971 2007/02/07 19:21

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング