前に作って愛用しているClosure Compiler ServiceのREST APIを叩くPerlスクリプトにローカルのJavaScriptファイルを読み込んでコンパイルに含められる機能を付けた。Closure CompilerのJARファイルを使ってローカルで動かしても良かったんだけど、APIやWeb UIのコメントでオプション設定を書く方法(Greasemonkey的な奴)が気に入っているので@code_path
というパラメーターを追加する形にした。
コンパイルするJavaScriptファイルでは
// ==ClosureCompiler==
// @code_path foo.js
// @code_path bar.js
// @code_url http://example.com/js/buz.js
// ==/ClosureCompiler==
というように@code_path
で取り込むJavaScriptファイルのパスを指定するだけ。@code_url
等の他のオプションとはバッティングしないけど、依存関係によって書く順序には注意する必要がある。これらに続けて普通にJavaScriptコードも書けるとかそこらへんはWeb UIと一緒。
コンパイル方法は前のと同じで標準入力と出力で。
$ gccs.pl <test.js >test.min.js
肝心のgccs.plは以下の通り。
#!/usr/bin/env perl
# gccs.pl - Compile your JavaScript code with Google Closure Compiler Service
# Usage: gccs.pl < <original file> > <compiled file>
# License: http://hail2u.mit-license.org/2009
# Modified: 2012-01-04T18:43:15+09:00
use strict;
use warnings;
use JSON;
use LWP::UserAgent;
use Path::Class qw();
my @params = (
"output_info", "compiled_code",
"output_format", "json",
);
&main;
exit;
sub main {
my @code = <STDIN>;
push @params, "js_code", join("", @code);
my $idx = 0;
my $found_metadata = 0;
while (my $line = $code[$idx++]) {
if ($line =~ /^\/\/ ==ClosureCompiler==/) {
$found_metadata = 1;
last;
}
}
if ($found_metadata) {
while (my $line = $code[$idx++]) {
if ($line =~ /^\/\/ ==\/ClosureCompiler==/) {
last;
} elsif ($line =~ /^\/\/ @(\S+)\s*(.*)$/) {
if ($1 eq "code_path" && -e $2) {
my $js_code = ";" . Path::Class::File->new($2)->slurp() . ";";
push @params, "js_code", $js_code;
} else {
push @params, $1, $2;
}
}
}
}
&compile(@params);
}
sub compile {
my $ua = LWP::UserAgent->new;
my $res = $ua->post("http://closure-compiler.appspot.com/compile", \@_);
if ($res->is_success) {
my $c = from_json($res->decoded_content);
if (defined $c->{"serverErrors"}) {
foreach (@{$c->{"serverErrors"}}) {
warn "Error(" . $_->{"code"} . "): " . $_->{"error"};
}
die "Failed to compile";
} else {
binmode STDOUT;
print $c->{"compiledCode"};
}
} else {
die $res->status_line;
}
}
一応セミコロンの無いダメなJavaScriptファイルのことも考慮して前後にセミコロンを挟んでやったりはしておいた。ちょっと美しくないけどClosure CompilerをSIMPLE_OPTIMIZATIONS以上で通せば消えるのでまぁ良いかなとか。
普通にバラバラにスクリプトを書いて、Makefile的なJavaScriptファイルで@code_path
を使って参照し、それをコンパイルとかで使ってください。cat
よりはマシ程度ですけどね!