Closure Compilerを使う!

よくある質問

最終更新:

aias-closurecompiler

- view
管理者のみ編集可

トップページ >

よくある質問

目次:

そもそも...

Closure Compilerとは何ですか?それを使うべき理由は?

Closure CompilerはJavaScriptのダウンロードと実行の速度を上げるためのツールです。あなたはClosure Compilerを使うことであなたのJavaScriptファイルのサイズを小さくでき、そしてコードはより効率的になります。

Closure Compilerはその他のJavaScript圧縮ツールとどう違うのですか?

一般的にClosure Compilerは他の縮小ツールと同等かそれ以上の圧縮率を達成しており、あなたのWebアプリケーションのダウンロード時間を改善することができます。加えて、Closure Compilerは文法エラーを開発中に(テスト中ではなく)発見すること、バグのパターンにはまる可能性のあるコードを見分けることを助けてくれます。

SIMPLE_OPTIMIZATIONS レベルの場合、Compilerはより一層のコードサイズ縮小を図るためにコンパイラ的なコード解析を行い、他のツールよりも優れた結果を実現します。Closure Compilerが行うことの例としては、数回しか出現しない関数のインライン化、変数名の再利用、定数式の事前計算があります。

ADVANCED_OPTIMIZATIONS レベルの場合、Closure Compilerはあなたが追加したデータ型に関するアノテーションも使って、目立たないバグを見つけ出します。

Closure Compilerを使うにはWeb開発の知識がどの程度必要ですか?

Closure CompilerはJavaScript開発のためのツールですので、Compilerを使うにはJavaScriptのプログラミングの知識が必須です。しかしJavaScriptを使う者なら誰でも、Closure Compilerを使うことで利益を得ることができます。

Compilerにとって、アプリケーションの実行速度とコードサイズの間には何らかのトレードオフがあるのでは?

はい。どんな最適化ツールにおいてもトレードオフは存在します。サイズ最適化は処理速度のオーバーヘッドをもたらすことがあります。しかしClosure Compilerの開発者は実行時間を大きく増加させないよう注意を払っており、むしろCompilerの行ういくつかの最適化処理は実行時間を短縮してさえいます。(次の質問を参照してください)

Compilerは処理速度を最適化しますか?

Webアプリケーションにおいて通常ダウンロード時間は処理速度の最も重要な要因ですので、ほとんどの場合、より小さいコードはより速いコードといえます。同様に、冗長性を減少させる最適化はコードの実行速度を向上させます。

Closure Compilerの使い方

Closure CompilerはHTMLに埋め込まれたJavaScriptをコンパイルできますか?

いいえ。Closure Compilerが処理できるのはJavaScriptだけを含むファイルに限定されます。

Closure Compilerを別の縮小ツールと一緒に使うことはできますか?

はい。Closure Compilerは正常なJavaScriptであればどんなものでも読み込みますし、自身も正常なJavaScirptを生成します。従って他の縮小ツールが出力したコードをCompilerに扱わせることも、逆にCompilerが出力したコードを他のツールに扱わせることも可能です。

Closure Compilerも他のツールも、入力されるコードについてある種の前提を置いている可能性があることを忘れないでください。例えばあるツールが削除したコメントの中には、他のツールが必要としているライセンス情報やアノテーションが含まれているかもしれません。

Closure CompilerをCajaと一緒に使うことはできますか?

Closure CompilerチームとCajaチームはClosure Compilerの SIMPLE_OPTIMIZATIONS レベルにおいてCajaのセマンティクスと安全性が確保できるように努力しています。しかし我々がそのゴールに到達したと保証できるまでには、更なるテストが必要です。もしあなたが SIMPLE_OPTIMIZATIONS レベルでの処理後にCajaのセマンティクスと安全性を保全できなくなるようなケースを見つけた場合、それをClosure Compilerのバグとして記録してください。そしてもしあなたが検証作業を手伝うことに興味があるなら、Cajaチーム(google-caja-discussグループへどうぞ)かClosure Compilerチーム(closure-compiler-discussグループへどうぞ)へ連絡をお願いします。

コンパイルできるファイルのサイズには制限がありますか?

Webサービス版(Closure Compiler Service UIClosure Compiler Service API)のコンパイルにはファイルサイズの最大値がありますが、スタンドアロン版(Closure Compiler Application)のアプリケーションには制限はありません。

Closure Compilerは全てのプラットフォームで使用できますか?

CompilerはJavaで書かれているので、Javaが動作すればどこででも使用できます。

Closure Compilerは文法的に正しければどんなJavaScriptでも処理できますか?

大部分は。 eval() with() のようなJavaScriptの言語構造のいくつかは、Compilerの変換処理が基づいている仮定を無効化します。

Closure CompilerはClosure Libraryとどのように連携しますか?

Closure CompilerはClosure Libraryを使用するコードに対して特別なチェックと最適化を行ないます。加えてClosure Compiler Service APIはClosure Libraryのファイルを自動的にインクルードする機能を持っています。Closure Compiler Service APIとClosure Libraryを一緒に使うための情報はAPIリファレンスを参照してください。Closure Compiler ApplicationとClosure Libraryを一緒に使うには、まずClosure Libraryをダウンロードしてください。Closure Compiler ApplicationのClosure Libraryサポートはデフォルトで有効になっています。

Finding Your Way around ClosureにはClosure Libraryのパーツの宣言方法が説明されています。

私はソースコードに必ず表記しなければならない著作権やライセンスの項目を持っています。これらをClosure Compilerが行うテキストの除去から守るにはどうしたらよいですか?

Closure CompilerはJSDocの @license タグをサポートしています。 @license タグを含む全てのJSDocコメントは、Compilerの出力の中で保護されます。より詳しい情報はアノテーションによる型定義を参照してください。

私の変数がページ上の他のスクリプトと確実に衝突しないようにするにはどうしたらよいですか?

まさにその目的のために、Closure Compilerは--output_wrapperオプションを持っています。それは次のように呼び出されます:

--output_wrapper "(function() {%output%})();"

こうするとコンパイルされたコードは無名関数にラップされるため、グローバルスコープを汚染することはありません。

Closure CompilerをJava APIから呼び出すにはどうすればよいですか?

Java APIのための正式なチュートリアルはまだありません。このブログの中の短いコードスニペットは、我々のみるところ、その方法を示す素晴らしく簡潔なデモであると思います。

もしあなたがClosure Compilerのソースコードを見たのであれば、AbstractCommandLineRunner.javaCommandLineRunner.javaがコマンドラインオプションをJava APIの呼出しに変換するために大きな役割を果たしているのが分かったはずです。そして何かピンとくるものがあったのではないでしょうか。Java APIの包括的なリファレンスとしては、参照しやすいようにJavaDocがSVNにチェックインされています。JavaDocには常にその時点のtrunkの状態が反映されています。

Closure Compilerがスレッドを使用する点に注意してください。多くのJavaの実装(例えばGoogle App Engineのような)はスレッドをサポートしていないため、あなたはdisableThreadsメソッドをコールする必要があるかもしれません。

Externファイルをどう書いたらよいのでしょう?

externファイルにはあなたのコードの外側にある(あるいは"external"な)APIを定義します。そこにはあなたがやりとりしたいと思っている外部の変数、型、プロパティが全て定義されているべきです。例えばClosure CompilerはwindowやDOMを扱うためのブラウザAPIについて何も知りませんが、代わりに我々はブラウザAPIを定義したデフォルトのexternファイルをClosure Compilerに搭載しました。このデフォルトセットはおそらくexternファイルの書き方についての最良のサンプルでしょう。見てのとおり、そこでは window のようなグローバル変数、 Range のようなデータ型、 Window.prototype.alert のようなプロパティなどが定義されています。

http://code.google.com/p/closure-compiler/source/browse/#svn/trunk/externs

もしあなたが一般に広く知られているAPI(Google Maps APIのような)のexternファイルを必要としているなら、先ずclosure-compiler-discussで誰かが既にそれを書いていないか尋ねてみてください。externファイルのさらに詳しい情報はこのページでみることができます。

予想外の結果

ADVANCED_OPTIMIZATIONSでコンパイルするとコードが動かなくなるか、Compilerがエラーを出力します。なぜでしょう?

ADVANCED_OPTIMIZATIONS を導入する場合、通常いくつかの準備とコードの書き換えが必要になります。Compilerが求めるコーディングルールには、あなたのコードを ADVANCED_OPTIMIZATIONS レベルで動作させるにはどうしたらよいかが説明されています。

Compilerが次のようなエラーを出してクラッシュしてしまいました: Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file

Closure CompilerはJava 6を必要とします。これはJavaのバージョンをアップグレードするように促すJava流の表現です。

" Trailing comma is not legal "というエラーを受け取りましたが、そのコードはFirefoxで動いています。

しかしInternet Explorerではそうではありません。

IEでは、オブジェクトリテラル {key: value,} はエラーです。
配列リテラル [1,] はエラーにはなりませんが、その解釈はForefoxとは異なります:

[1,].length
=> 1 (on Firefox)
=> 2 (on IE)

この違いはバグにつながる可能性が非常に高いため、明確に禁止しています。

" Unsupported syntax "というエラーを受け取りましたが、そのコードはFirefoxで動いています。

FirefoxにはJavaScript 1.5以後のクールな新機能が盛り込まれています。Closure CompilerはJS1.5と後方互換性を持たないいかなる仕様もサポートしません。それらには次のものも含まれます:

Closure Compilerが文字列をインライン化したため、コードサイズが大きくなってしまいました。なぜこんなことをするのでしょう?

ほとんどの人は圧縮されていないJavaScriptファイルを並べてコードサイズの大小を比較します。しかしこれはコードサイズの見方をミスリードするものです。なぜならあなたのJavaScriptファイルはgzip圧縮された状態で配信されるはずだからです。

Closure Compilerはあなたがgzip圧縮を使用していることを想定しています。もしそうでないなら、そうすべきです:コードのgzip圧縮は、考えられる内で最も効果的でしかも簡単な最適化手法のひとつです。

gzipのアルゴリズムはバイトシーケンスを最善の方法で別名に置き換えようとします。手動で文字列を別名にまとめるとほとんどの場合圧縮したときのコードサイズはかえって大きくなりますが、これはその作業がgzip自身の別名化アルゴリズムの効果を覆すものだからです。つまりClosure Compilerが(ほとんど)常に可能な限りの文字列をインライン化しようとするのは、圧縮されたときにコードがより小さくなるようにするためなのです。

Closure Compilerの設計について

なぜコンパイルされたコードはランダムに改行されているのですか?

Closure Compilerは約500文字ごとに意図的に改行を挿入します。ファイアウォールやプロキシは時々1行が非常に長いJavaScriptファイルを破損したり無視したりすることがあり、500文字ごとの改行はそれを防止するためのものです。改行を削除してもスクリプトのセマンティクスには影響がありません。ただ改行がコードサイズに与えるインパクトは小さく、またCompilerはファイルをgzip圧縮したときに悪影響がより小さくなるよう、改行の位置を最適化しています。

JSDocの型言語の仕様書はありますか?

Closure Compilerの型言語はEcmaScript 4 draft spec(ここには型言語の厳格な文法と、それが意図するセマンティクスが説明されています)に可能な限り準拠しようとしています。

もっとくだけたチュートリアルもこちらのページにあります。

Closure Libraryを眺めていると、実際のタイプアノテーションの構文が仕様書と異なっていることに気づくかもしれません。しかしそれらは正しく解釈されており、通常、意図的なものです。我々が実装したEcmaScript 4 draftの仕様は流動的で、我々がサポートしているいくつかの文法は既に過去のものになっています。(それらの大部分は、型の結合に用いられる特定の演算子の順序に関するものです)

別な○○という構文をJSDocの型言語に追加してもらえませんか?

もし〇〇が以前はできなかった何かを可能にするのであれば、先ずあなたのアイデアをclosure-compiler-discussに提案してください。

もし〇〇が他の方法で実現可能なのであれば、99%答えはノーです。

我々のJSDocの型言語をパースしているツールは既に多く存在します。新しい構文を追加した場合、それはそれらのツール全てがアップデートの必要に迫られることを意味します。ドキュメントの更新も必要ですし、JavaScript開発者はそれを学ばなければなりません。型言語はより複雑化するため、新しいツールの作成は困難になります。

新しい構文が本当の価値をそこに加えるのでなければ、我々はこのようなコストを正当化できません。

私はFirefoxのエクステンションを書いています。それは最新版のFirefoxでさえ動作すればよく、他のブラウザで動かなくても問題はありません。JavaScript 1.7で導入されているカッコいい機能を利用できるよう、 --platform=FIREFOX オプションを追加できませんか?

概ね、ノーです。理由は2つあります。

第1に、我々は怠け者です。かつてClosure Compilerの処理系は主にGoogleエンジニアのボランティアによって書かれていて、その頃の開発サイクルといえばこんな感じでした:"やあ!今のアプリの動作は遅いけど、この最適化処理を加えればもっと速くなるよ。午後にそのコードを書いて、それから通常業務に戻るとしよう。" ほとんどの開発者はJavaScriptのエキスパートではありません。従ってJavaScriptの2種類のバリエーションを理解しなくてよいことは、開発者達が新しい処理系を書くことを容易にするという点で我々にはとても重要だったのです。

第2に、我々はコードを共有することが好きです。私が自分のFirefoxエクステンションのためのJavaScriptクラスを書き、そこではFirefoxだけで有効なキーワードが使われているとしましょう。2ヶ月後、友人のKushalがそれを気に入り、彼のWebアプリに組み込もうとします。彼のWebアプリはInternet Explorer上で動作する必要があります。しかし全てのgetterとsetterの書き換え はあまりに手間のかかる作業で、自分で最初からコードを書いたほうが早いと気づいた彼は組み込みを諦めてしまいました。これは私にも彼にも不幸です。そして分かったのは、コードがクロスブラウザで動作し、共有がしやすければ、誰もがより幸せになれるということです。


目安箱バナー