Closure Compiler Service API を使用したファイルの圧縮

Closure コンパイラ サービスのサポートが終了し、今後削除されます。 代わりにコンパイラをローカルで実行することを検討してください。

概要

API との通信では、Closure Compiler サービスとの通信方法の基本について説明しましたが、API を使用して、JavaScript の 1 行からコメントを削除する方法だけを取り上げています。このチュートリアルでは、より現実的な開発シナリオ(JavaScript ファイル全体を処理してサイズを大幅に削減する)で Closure Compiler サービスを使用する方法について説明します。

このチュートリアルは、JavaScript と HTTP に関する基本的な知識があることを前提としています。Python スクリプトを使用して Closure Compiler サービスに JavaScript を送信しますが、この例に沿って Python を知る必要はありません。

  1. ファイルの圧縮
  2. 圧縮の改善
    1. コードがどれだけ小さくなるか
    2. Closure Compiler Service でプログラムの規模を縮小したのはなぜですか?
  3. 対処方法

ファイルの圧縮

API と通信するの例では、コマンドライン パラメータとして JavaScript 文字列をコンパイル スクリプトに渡します。しかし、このサイズは、実数規模の JavaScript プログラムではうまくいきません。コードが数行を超えると JavaScript 文字列はすぐに手に負えなくなります。大規模なプログラムの場合は、code_url リクエスト パラメータを使用して、処理する JavaScript ファイルの名前を指定できます。js_code に加えて、code_url を使用するか、js_code の代わりに使用できます。

たとえば、次の JavaScript プログラムについて考えてみます。

/**
 * A simple script for adding a list of notes to a page. The list diplays
 * the text of each note under its title.
 */

/**
 * Creates the DOM structure for a note and adds it to the document.
 */
function makeNoteDom(noteTitle, noteContent, noteContainer) {
  // Create DOM structure to represent the note.
  var headerElement = document.createElement('div');
  var headerText = document.createTextNode(noteTitle);
  headerElement.appendChild(headerText);

  var contentElement = document.createElement('div');
  var contentText = document.createTextNode(noteContent);
  contentElement.appendChild(contentText);

  var newNote = document.createElement('div');
  newNote.appendChild(headerElement);
  newNote.appendChild(contentElement);

  // Add the note's DOM structure to the document.
  noteContainer.appendChild(newNote);
}

/**
 * Iterates over a list of note data objects and creates a DOM
 */
function makeNotes(data, noteContainer) {
  for (var i = 0; i < data.length; i++) {
    makeNoteDom(data[i].title, data[i].content, noteContainer);
  }
}

function main() {
  var noteData = [
      {title: 'Note 1', content: 'Content of Note 1'},
      {title: 'Note 2', content: 'Content of Note 2'}];
  var noteListElement = document.getElementById('notes');
  makeNotes(noteData, noteListElement);
}

main();

このプログラムは、1 つの大きな文字列ではなく、ファイルとして Closure Compiler サービスに簡単に渡すことができます。サービスを使用してファイルを処理する手順は次のとおりです。

  1. JavaScript をファイルに保存します。
  2. ファイルをウェブからアクセスできるようにします(ウェブサーバーにアップロードするなど)。
  3. API との通信に示すように、Closure Compiler サービスに POST リクエストを送信します。ただし、js_code パラメータに code_url パラメータを指定します。code_url の値は、ステップ 1 で作成した JavaScript ファイルの URL にする必要があります。

たとえば、この例の JavaScript は tutorial2.js ファイルにあります。このファイルを Closure Compiler Service API で処理するには、code_url を使用するように Python プログラムと API の通信から変更します。

#!/usr/bin/python2.4

import httplib, urllib, sys

# Define the parameters for the POST request and encode them in
# a URL-safe format.

params = urllib.urlencode([
    ('code_url', sys.argv[1]), # <--- This parameter has a new name!
    ('compilation_level', 'WHITESPACE_ONLY'),
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

# Always use the following value for the Content-type header.
headers = { "Content-type": "application/x-www-form-urlencoded" }
conn = httplib.HTTPSConnection('closure-compiler.appspot.com')
conn.request('POST', '/compile', params, headers)
response = conn.getresponse()
data = response.read()
print data
conn.close()

注: このサンプルを再現するには、Windows ユーザーが Python のインストールが必要になる場合があります。Windows で Python をインストールして使用する手順については、Python Windows に関するよくある質問をご覧ください。

次のコマンドを使用して、コードを Closure Compiler サービスに送信します。

$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js

Closure Compiler サービスは https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js からファイルを取得し、レスポンスで圧縮された JavaScript を返します。

複数の出力ファイルを 1 つの出力ファイルにコンパイルするには、次の例に示すように複数の code_url パラメータを含めます。

params = urllib.urlencode([
    # Multiple code_url parameters:
    ('code_url', 'http://yourserver.com/yourJsPart1.js'),
    ('code_url', 'http://yourserver.com/yourJsPart2.js'),
    ('compilation_level', 'WHITESPACE_ONLY'),
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

圧縮の改善

これまでの例では、WHITESPACE_ONLYcompilation_level を使用していました。コメントと空白文字を削除するだけです。SIMPLE_OPTIMIZATIONS 圧縮レベルを使用すると、圧縮率がはるかに高くなります。SIMPLE_OPTIMIZATIONS 圧縮を使用するには、compilation_level パラメータを SIMPLE_OPTIMIZATIONS に変更します。

params = urllib.urlencode([
    ('code_url', sys.argv[1]),
    ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),  # <--- This parameter has a new value!
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

前と同様にスクリプトを実行します。

$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js

出力は次のようになります。

var GLOBAL_document=document,$$PROP_appendChild="appendChild";function makeNoteDom(a,b,c){var d=GLOBAL_document.createElement("div");a=GLOBAL_document.createTextNode(a);d[$$PROP_appendChild](a);a=GLOBAL_document.createElement("div");b=GLOBAL_document.createTextNode(b);a[$$PROP_appendChild](b);b=GLOBAL_document.createElement("div");b[$$PROP_appendChild](d);b[$$PROP_appendChild](a);c[$$PROP_appendChild](b)}function makeNotes(a,b){for(var c=0;c<a.length;c++)makeNoteDom(a[c].title,a[c].content,b)}
function main(){var a=[{title:"Note 1",content:"Content of Note 1"},{title:"Note 2",content:"Content of Note 2"}],b=GLOBAL_document.getElementById("notes");makeNotes(a,b)}main();

このコードはソース プログラムよりも読みにくいですが、そのサイズは小さくなっています。

コードがどれだけ小さくなるか

リクエスト パラメータの output_infocompiled_code から statistics に変更すると、どのくらいのスペースが削減されたかを正確に確認できます。

Original Size: 1372
Compressed Size: 677
Compilation Time: 0

新しい JavaScript が元のサイズの半分未満になっています。

Closure Compiler Service でプログラムの規模縮小を実現したのはなぜですか?

この場合、Closure Compiler はローカル変数の名前を変更することで、サイズを小さくできます。たとえば、元のファイルには次のコード行が含まれています。

var headerElement = document.createElement('div');

Closure Compiler の文は以下のように変更されます。

var d=document.createElement("div");

クロージャ コンパイラは、関数 makeNoteDom 内のどこでもシンボル headerElementd に変更し、機能を保持します。ただし、headerElement の 13 文字が、表示される 3 つの場所それぞれで 1 文字に短縮されています。これにより、合計で 36 文字の削減が可能になります。

SIMPLE_OPTIMIZATIONS でコンパイルすると、文字列名(たとえば、eval() ステートメント)を使用してローカル変数にアクセスしない限り、構文的に有効な JavaScript の機能が保持されます。

次のステップ

SIMPLE_OPTIMIZATIONS とそのサービスの使用に関する基本的な仕組みを理解したところで、次に ADVANCED_OPTIMIZATIONS のコンパイル レベルについて学習します。このレベルでは、JavaScript がコンパイル前後で同じように動作するように、追加の手順が必要になりますが、JavaScript はさらに小さくなります。ADVANCED_OPTIMIZATIONS については、高度なコンパイルとエクスターンをご覧ください。