HOME > 開発者向けBLOG > Sencha Blog >  Sencha Cmd 内の JS 圧縮方法の比較

Technology Note 開発者向けBLOG

Sencha Blog

Sencha Cmd 内の JS 圧縮方法の比較

こんにちは、ゼノフィnakamuraです。

この記事は、US Sencha社ブログ Comparing JS Compression Methods in Sencha Cmd を翻訳したものです。

Introduction

何年も何年も、ウェブ開発者は制作環境のためにコードを最適化しなければならないと言われ続けてきました。世間一般の通年では、アプリケーションが必要としている JavaScript を全て圧縮するだけで、使用帯域幅は削減され、アプリケーションのロードは非常に早くなるとされています。Sencha はこの手順を Sencha Cmd を通し、何年間も自動化させることを手助けしてきています。

しかし、多くのお客様も気づいていないかもしれませんが、Sencha Cmd がどのようにコードを圧縮するかをいじることで、更ならるパフォーマンス向上を見込むこともできます。Sencha Cmd はこのタスクのためにデフォルトで YUI Compressor を使用しますが、ビルドアウトプットを Google Closure もしくは UglifyJS を代わりに使用するように設定をすることもできます。そして、この記事を読んでいただければわかりますが、どの圧縮ツールを使用するかはテストする価値は十分にあります。

この記事は、特定のツールをお勧めする内容ではありません。数ある圧縮ツールの中から1つを選ぶということは、ケースバイケースであり、そういった様々な状況で判断を下さなければいけない時にこういったアプローチもあるということを指し示す内容となっております。

なぜデフォルト設定を変更したいと思うのか?

JavaScript のコンプレッサーの仕組みは複雑に感じるかもしれませんが、基本的な理念は非常に単純なものです。あなたのコードはトークン化され、アブストラクトシンタックスツリー(AST) に構文解析 (パース )され、アウトプットを圧縮するために変更された JavaScipt プログラムとして再生成されます。

こういったツールが具体的にどのように働くか (どういったアルゴリズムが使用されているかなど )はこの記事の狙いではないですが、簡単に YUI コンプレッサー、Closure、そして UglifyJS が どういったものかをハイレベルで解説していきましょう。

YUI Compressor

YUI コンプレッサーは、Java で書かれたコマンドラインユーティリティーです。JavaScript と CSS 両方の圧縮に対応しているので、多くのプロジェクトでは理想的なツールとされています。YUI コンプレッサーについては 非推奨となっていますが 、まだ一定の人気は保っています。

前述の通り、Sencha Cmd はアプリケーションのビルド処理においてデフォルトで YUI Compressor を使います。

Google Closure Compiler

Google Closure Compiler も Java で作られています。しかし、JavaScript 圧縮にしか対応していません (CSSには非対応 )。Closure はコマンドラインから直接実行することができ、付属のサービスがあり (UI、API)、コードアノテーションやコンピレーションフラグを使うことで圧縮プロセスをより制御することができます。

UglifyJS

UglifyJS はこれらのツールの中で唯一 JavaScript で書かれています。そのため、Node.js 環境では重宝されます。Closure のように、JavaScript の圧縮にしか対応していません。UglifyJS はコマンドラインユーティリティーとして実行され、幾つかのコンピレーションフラグを通して圧縮プロセスを制御することができます。

記:Sencha Cmd は Javaで作られているため、UflifyJS は Node.js ではなく Rhino で実行されます。

各ツールは微妙に違う圧縮アウトプットを出力し、どのツールが一番最適な結果を出すかは予測することが難しいことを頭に入れておいてください。この点をわかりやすくするために、サンプルアプリケーションを利用し、各ツールがどのようにコードを扱うかを見ていきましょう。

ケーススタディー: Ext JS 5 サンプルアプリ

このコンセプトを表現するために一番簡単な方法は Sencha Cmd を使ってサンプルアプリケーションを生成することでしょう:

     sencha -sdk ~/path/to/ext generate app Foo ./foo

Sencha Cmd は、完全に機能するサンプルアプリケーションの雛形を組めるため、他に何ひとつする必要はありません。アプリケーションを Firefoxで実行するとし、「開発」アプリは以下のステータスでロードされます:

ここには特別驚くポイントはありません。「開発」モードの Ext JS アプリケーションは、各 JavaScript の依存関係を同期的にロードするために Ext.Loader に依存しています。また、0.29s は 24HTTP リクエストを待つために大した時間ではありませんが、企業用アプリケーションではどれくらい時間がかかるかは想像しやすいしょう。

sencha app build を実行し、サンプルアプリを「プロダクション」にすると、ネットワーク統計に多少の変化が見られます:

明らかに JavaScript リソースは削減され、全体のロード時間は 0.02s まで短縮されました! これは全て JavaScript 圧縮の魔法のおかげなのです。

JavaScript 圧縮の必要性は当然だとわかりましたが、Sencha Cmd の設定をいじることで、さらに良い結果を出すということは可能なのでしょうか?どの圧縮ツールを使用するかを変更するため、app.json ファイルを編集しましょう:

{
    //...
 
    /**
     * override objects for setting build environment specific
     * settings.
     */
    "production": {
        "compressor" : {
            //"type" : "yui"    //the default...
            //"type" : "uglify" //or...
            "type" : "closure"
        }
    },
 
    //...
}

ここで sencha app build を実行すると、ビルドプロセスは設定された圧縮ツールを使用します。次に、サンプルアプリケーションで使用した複数の圧縮ツールの結果を見ていきましょう。

 コンプレッサー  ファイルサイズ (バイト)  オリジナルとの比率 (%)
 (なし)  5,166,339  100.0%
 YUI  1,109,534  21.48%
 Closure  1,081,242  20.93%
 UglifyJS  1,069,126  20.69%
 YUI (gzip)  343,696  6.65%
 Closure (gzip)  323,615  6.26%
 UglifyJS (gzip)  329,182  6.37%

上記の表では、実際の圧縮ファイルサイズだけでなく、その圧縮されたアウトプットファイルを gzip したもの (デフォルトの設定で gzip ターミナルコマンドを経由して実行)も表示されています。興味深いのは UglifyJS が一番小さいアウトプットをビルドプロセスで示したにも関わらず、更なる gzip 圧縮を考慮すると Closure の方が優れていたという点です。


もし gzip 設定もいじっていれば、より良い結果が得られていたかもしれません。

考慮点

Closure の勝利です、ということでこれからは皆さんは Closure を使用しましょう…というわけには残念ながらなりません。

もし、更に一歩踏み込んで、ビルドプロセスを実行するトータルの時間 (CSSテーマを生成したりその他の手順を含め )も測ると重要なことに気づくことができました。

サンプルアプリは Ext JS 5.0.1.1255 を使用し、コマンドは Sencha Cmd 5.1.0.26 を使い、MacBook Pro は以下のスペックです(2011年の始めに購入、OSX 10.10.1、2GHz Intel i7、 8GB RAM)。結果は使っているマシンによって変わるでしょう。記:ビルド設定を変更し、古いブラウザのためのテーマスライスを外しました。

     sencha -ti app build -c

上記のコマンドで、実行するための総合時間が提供されます(-ti flag)、そして過去のビルドアウトプッとも除外し (-c flag)、比較が公平なものだと保証します。各圧縮ツールでビルドを実行すると、なぜ YUI コンプレッサーがデフォルトの選択肢かわかります:

  • YUI: 0:00:33
  • Closure: 0:00:54
  • UglifyJS: 0:15:40

Closure はビルドアウトプットを圧縮するのに約2倍、UglifyJS は約3倍も時間がかかりました! ここでのポイントは、数キロバイトを削減するために、ビルド時間の大きな増加を選択できるのかということです。

究極的に言えば、数キロバイトの削減というのは大きな結果であり、JavaScript のサイズを小さくするという最初の目的を達成できています。しかし、ハイトラフィックなアプリケーションは、こういった時間の詳細に関しては慎重になるべきかもしれません。ページのスピードや全体の帯域が 直接利益に影響を与えてしまう からです。

最終的に、もしかしたら圧縮された JavaScript が圧縮後により早く実行されたかが気になるかもしれません。しかし、それを知るのは不可能に近いことであり、既存の JSPerf テストでは、仮想的にはその実行のスピードに相違はないと言われています。

JS 圧縮のカスタマイズ

Sencha Cmd は、現在では YUI コンプレッサーの設定を変更できない仕様になっています。しかし、そもそも YUI コンプレッサーはそこまで変更できるものではありません。Sencha Cmd では、Closure がどの様にソースコードをコンパイルするかは設定することができます。

app.json を開き、Closure の コンパイルオブジェクト を直接 “compressor” オブジェクト上で設定できます。

{
    //...
 
    "production": {
        "compressor" : {
            "type" : "closure",
 
            //all other keys are passed as options
            "ambiguateProperties" : true,
            "foldConstants"       : true
        }
    },
 
    //...
}

Sencha Cmd では UglifyJS のカスタム設定はまだ実装されていませんが、いずれされる予定となっています。

まとめ

JavaScript を圧縮するということは、ウェブアプリケーションのパフォーマンスを向上させるためには非常に合理的なベストプラクティスだと言えます。Sencha Cmd はこのプロセスをデフォルトで自動化してますが、さらにプロダクションビルドを最適化させるために、詳細設定をいじるのも1つの手かもしれません。

PAGETOP