Javaスクリプト圧縮

Google Closure Compilerを利用したPHPクラスを作ってみる

前回の記事で利用した、Google Closure Compilerを使ってJavaスクリプトを圧縮するツールを作成してみます。

HTMLから呼び出すJavaスクリプトをPHPファイルにする

Javaスクリプトは、基本的には「*.js」ファイルですがPHPを指定することもできます。

もちろん指定したPHPが、Javaスクリプトを出力しなければなりません。

 

HTMLにてJavaスクリプト定義にPHPを指定する例

<script type="text/javascript" src="js.php"></script>

 

複数のJavaスクリプトを1つにまとめて、圧縮して出力するPHPクラス

これを利用して、複数のJavaスクリプトを1つにまとめて、圧縮して出力するPHPクラスを作成してみました。

ただまとめて圧縮するだけだと、表示するたびに処理が必要で遅くなるためキャッシュファイルを作成するようにしました。

class jsCompresser{
	
	private $s=Array();						//JavaScriptライブラリ パス配列
	private $cacheTime = 1209600;			//キャッシュ時間(ミリ秒) デフォルト2週間
	private $cacheDir = __DIR__."/";		//キャッシュ出力フォルダ
	private $cacheFile = null;				//キャッシュファイル名
	private $Error = "";					//エラーメッセージ
		
	private $compilation_level='SIMPLE_OPTIMIZATION';
	
	/**
	 * コンストラクタ
	 * @param type $version
	 */
	function __construct($version=""){
		//キャッシュファイル名作成
		if($version == "" || $version == null) {
			
			//指定が無い場合は、対象フォルダを検索
			$files = glob($this->cacheDir.'cache.*.js');
			
			//存在する場合
			if($files != false) {
				//既存のキャッシュファイルを設定
				$this->cacheFile = $files[0];
			} else {
				//キャッシュファイル名を作成
				$this->cacheFile = $this->cacheDir.'cache.'.md5(date("Ymd")).'.js';
			}
		}else{
			//指定がある場合は、指定文字列でキャッシュファイルを作成
			$this->cacheFile = $this->cacheDir.'cache.'.md5($version).'.js';			
		}
	}
	/**
	 * 圧縮レベルを設定
	 * @param type $Level
	 *  WHITESPACE_ONLY				空白&コメント&改行削除
	 *  SIMPLE_OPTIMIZATIONS		上記plus 変数名省略可
	 *  ADVANCED_OPTIMIZATIONS		解析して高圧縮
	 */
	public function setCompilationLevel($Level){
		$this->compilation_level =$Level;
	}
	/**
	 * 対象のスクリプトを設定する
	 * @param type $key		lib:ライブラリ、js:圧縮対象ファイル、code:JavaScriptコード
	 * @param type $val
	 */
	public function setScript($key,$val)
    {
        $this->s[] = array($key=>$val);
    }	
    /**
    *  キャッシュの有効時間を設定する
    *  @param $cacheTime      int   キャッシュ時間(ミリ秒)
    */	
	public function setCacheTime($cacheTime)
    {
        $this->cacheTime = $cacheTime;
    }	
	/**
    *  キャッシュの出力フォルダを指定する
    *  @param $cacheDir      text   キャッシュの出力フォルダ
    */	
	public function setCacheDir($cacheDir)
    {
        $this->cacheDir = rtrim($cacheDir,'/').'/';
		//指定が無い場合は、対象フォルダを検索
		$files = glob($this->cacheDir.'cache.*.js');

		//存在する場合
		if($files != false) {
			//既存のキャッシュファイルを設定
			$this->cacheFile = $files[0];
		} else {
			//キャッシュファイル名を作成
			$this->cacheFile = $this->cacheDir.'cache.'.md5(date("Ymd")).'.js';
		}
    }	
	/**
    *  圧縮したJavaスクリプトを取得する
    *  @param なし
    */	
	public function getMinJs()
    {
        $MinJs = "";

		//キャッシュが有効か確認する。
		if($this->_chkCache()){
			//キャッシュが有効なので、キャッシュ内容を返す
			return file_get_contents($this->cacheFile);
		} else {
			//キャッシュが無効なので、対象フォルダからキャッシュを削除
			$files = glob($this->cacheDir.'cache.*.js');
			for($i = 0;count($files) > $i;$i++) {
				unlink($files[$i]);
			}
		}
		
		//各種別ごとに内容をまとめる
		for($i = 0;count($this->s) > $i;$i++) {
			foreach ($this->s[$i] as $key => $value){
				switch ($key) {
					case 'lib':
						$lib .= file_get_contents($value);
						break;
					case 'js':
						$MinJs .= file_get_contents($value);
						break;
					case 'code':
						$MinJs .= $value;
						break;					
				}	
			}
		}
		
		//圧縮対象コードがサイズオーバーの場合
		if(strlen($MinJs) > 200000) {
			//ダメもとで、タブや改行を削除
			$MinJs = preg_replace( "/(\t|\r\n|\r|\n)/s", "", $MinJs);
		}
		
		//ライブラリと圧縮結果を取得
		$MinJs = $lib.$this->_miniJS($MinJs);
		
		//圧縮でエラーが発生していた場合
		if(strlen($this->Error) > 0) {
			//エラーメッセージを戻す
			$MinJs = $this->Error;
		} else {
			//正常なので、キャッシュファイルを作成
			file_put_contents( $this->cacheFile, $MinJs );
		}
		
		
		return $MinJs;
    }
	
	/**
	 * キャッシュファイル有効チェック
	 * @return boolean
	 */
	private function _chkCache(){
		// キャッシュファイルが無い
		if ( !is_file($this->cacheFile) ) {
			return false;
		}
		
		//キャッシュファイルの日付を取得
		$cftime = filemtime($this->cacheFile);
		if ( !$cftime ) {
			return false;
		}
		// キャッシュ有効時間を過ぎている
		if ( time() > ($this->cacheTime + $cftime) ) {
			return false;
		}	
		
		for($i = 0;count($this->s) > $i;$i++) {
			foreach ($this->s[$i] as $key => $value){
				//Jsとlib以外は行わない
				if($key != 'js' &&  $key != 'lib' ) continue;			
				//ファイル日付を取得
				$jftime = filemtime($value);
				if ( !$jftime ) return false;				
				//キャッシュファイルより新しい場合
				if ( $cftime < $jftime ) return false;
			}
		}	
		
		return true;
	}
	
	/**
	 * Google Closure Compilerで圧縮実体
	 * @param type $js
	 * @return type
	 */
	private function _miniJS($js){


		$ch = curl_init('http://closure-compiler.appspot.com/compile');

		curl_setopt($ch,CURLOPT_POST,true);
	
		curl_setopt($ch, CURLOPT_POSTFIELDS,
			'output_format=json'
			.'&output_info=compiled_code'
			.'&output_info=warnings'
			.'&output_info=errors'
			.'&compilation_level='.$compilation_level
			.'&js_code=' . urlencode($js)
		);	
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
		curl_setopt($ch, CURLOPT_TIMEOUT, 30);

		$minified = curl_exec($ch);

		curl_close($ch);
		$rec=json_decode($minified);
		
		if(isset($rec->errors)) {
			for($i = 0;count($rec->errors) > $i;$i++) {
				foreach ($rec->errors[$i] as $key => $value){
					$this->Error .= $key.':'.$value.'\n';
				}
			}
			return '';
		}
		return $rec->compiledCode;
	}
}
コンストラクタ 引数として文字列を渡すことで、任意のキャッシュファイル名を作成します。

省略時には、処理日をmd5ハッシュ値にし作成します。

setCompilationLevel 圧縮レベルを指定します。(デフォルト SIMPLE_OPTIMIZATIONS)

WHITESPACE_ONLY 空白&コメント&改行削除
SIMPLE_OPTIMIZATIONS 上記plus 変数名省略可
ADVANCED_OPTIMIZATIONS 解析して高圧縮

setScript 対象のスクリプトパス、またはコードを設定します。

※libは圧縮されません。js+codeを圧縮します。

※どの順番で指定した場合でも、libは先頭に出力されます。

lib ライブラリ

js  圧縮対象ファイル

code JavaScriptコード

setCacheTime キャッシュの有効時間をミリ秒で設定(デフォルト2週間)
setCacheDir キャッシュの出力フォルダを指定します(デフォルトPHPパス)
getMinJs setScriptで指定したコードを圧縮し戻します。

 

 

上記クラスの呼び出しサンプル

w2uiライブラリを使ってJavaスクリプトを作成していると、かなり大きなファイルになってしまいます。

設定部や処理部など、ファイルを分割しておいて、HTMLから呼び出されたときにまとめて圧縮して出力しています。

//クラス作成
$js = new jsCompresser();

//キャッシュ出力フォルダ
$js->setCacheDir(__DIR__);

//対象Javaスクリプト(行順に出力)
$js->setScript("lib",__DIR__."/jquery.js");
	
$js->setScript("js",__DIR__."/global.js");
$js->setScript("js",__DIR__."/myclass.js");

$js->setScript("code","$(function () {w2utils.locale('locale/ja-jp.json');");

$js->setScript("js",__DIR__."/settings.js");
$js->setScript("js",__DIR__."/function.js");	

$js->setScript("code","})");

//圧縮レベルの設定
$js->setCompilationLevel('ADVANCED_OPTIMIZATIONS');

//設定したスクリプトを圧縮して表示
echo $js->getMinJs();

 

本来ならコンパイルしてくれるツールなど沢山あるのでしょうが、PHPクラスにしておけばある程度環境に左右されないかと思います。

パッと考えて作ったクラスなので、あまり自信をもって公開できるものではありませんが・・・(;´・ω・)

何かのお役に立てれば幸いです。

By にど寝

もともと名古屋でシステムエンジニアをしてましたが、現在は地元に帰省してネットショップの社内システムエンジニアをしてます。  

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です