- JScript + Closure Compiler(Windows上)で、ファルダ内のJavascriptソースコードを結合、コンパイルする。
- JREさえインストールされていれば利用可能。
- 文字コードはUTF-8(BOMなし)LFを想定。
- 依存関係はgoog.require()とgoog.provide()で指定。
- 出力ファイルにgoog.require()とgoog.provie()は含まれない。
- コンパイルの後処理で削除する。
- 出力ファイルにgoog.require()とgoog.provie()は含まれない。
- Pythonが利用可能なら、素直にそっちを使うべき。
- 組み込みのAntタスクはサポートしていない実行オプションがあったり、前処理、後処理を差し挟むのが面倒なので、ちょっと微妙。
build.js
var COMPILER = 'closure-compiler.jar';
var DEST_DEVELOPMENT = '../../dest.js';
var DEST_TEST = '../qunit/test.js';
var DEST_PRODUCTION = '../../dest.min.js';
var FOLDER_SOURCES = '../../sources';
var FOLDER_TESTS = '../../tests/qunit';
var FOLDER_EXTERNS = 'externs';
var ENCODING = 'utf-8';
var TEMPLATE = '"(function(window) {%output%})(window);"';
// Gets file names in a folder recursively.
var getFileNames = function(fileName) {
var fileSystem = new ActiveXObject('Scripting.FileSystemObject');
if (fileSystem.FileExists(fileName)) {
// If the file is a file (not a directory).
return [fileName];
}
if (!fileSystem.FolderExists(fileName)) {
return [];
}
var filenames = [];
// Searches a current folder.
var folder = fileSystem.GetFolder(fileName);
for (var e = new Enumerator(folder.Files); !e.atEnd(); e.moveNext()) {
filenames.push(e.item().Path);
}
// Seaches child folders.
for (var e = new Enumerator(folder.SubFolders); !e.atEnd(); e.moveNext()) {
filenames = filenames.concat(getFileNames(e.item()));
}
return filenames;
};
// Reads a file with UTF-8.
var readFile = function(fileName) {
try {
var stream = new ActiveXObject('ADODB.Stream');
stream.Type = 2;
stream.charset = ENCODING;
stream.Open();
stream.LoadFromFile(fileName);
return stream.ReadText(-1);
} finally {
stream.Close();
}
};
// Writes a text to a file with UTF-8 except a BOM.
var writeFile = function(fileName, text) {
try {
// Writes a text to a stream with UTF-8.
var stream = new ActiveXObject('ADODB.Stream');
stream.Type = 2;
stream.Charset = ENCODING;
stream.Open();
stream.WriteText(text);
// Changes a stream type.
stream.Position = 0;
stream.Type = 1;
// Skips a BOM and keeps a text.
stream.Position = 3;
var bytes = stream.Read();
// Resets a stream and writes a text to.
stream.Position = 0;
stream.SetEOS();
stream.Write(bytes);
// Saves a stream.
stream.SaveToFile(fileName, 2);
} finally {
stream.Close();
}
};
try {
// Runs Closure Compiler.
var runClosureCompiler = function(options) {
var command = 'java';
for (var key in options) {
switch (key) {
case '--externs':
case '--formatting':
for (var i = 0; i < options[key].length; i++) {
command += ' ' + key + ' ' + options[key][i];
}
break;
case '--js':
command += ' ' + key;
for (var i = 0; i < options[key].length; i++) {
command += ' ' + options[key][i];
}
break;
default:
command += ' ' + key + ' ' + options[key];
break;
}
}
var shell = new ActiveXObject('WScript.Shell');
var exec = shell.Exec(command);
while (exec.Status === 0) {
WScript.Sleep(10);
}
var errorMessage = '';
while (!exec.StdErr.AtEndofStream) {
errorMessage += exec.StdErr.ReadLine() + '\n';
}
if (errorMessage !== '') {
throw {command: command, errorMessage: errorMessage};
}
};
// Generates nx.js.
runClosureCompiler({
'-jar' : COMPILER,
'--charset' : ENCODING,
'--compilation_level' : 'WHITESPACE_ONLY',
'--manage_closure_dependencies' : 'true',
'--js_output_file' : DEST_DEVELOPMENT,
'--js' : getFileNames(FOLDER_SOURCES),
'--output_wrapper' : TEMPLATE,
'--formatting' : [
'pretty_print',
'print_input_delimiter'
]
});
// Removes Google directives from nx.js.
var content = readFile(DEST_DEVELOPMENT)
.replace(/goog\.require\(.*\);\s?/g, '')
.replace(/goog\.provide\(.*\);\s?/g, '');
writeFile(DEST_DEVELOPMENT, content);
// Generates nx.min.js.
runClosureCompiler({
'-jar' : COMPILER,
'--charset' : ENCODING,
'--compilation_level' : 'ADVANCED_OPTIMIZATIONS',
'--js_output_file' : DEST_PRODUCTION,
'--js' : [
DEST_DEVELOPMENT
],
'--externs' : getFileNames(FOLDER_EXTERNS),
'--output_wrapper' : '"(function() {%output%})();"'
});
// Generates test.js.
if (FOLDER_TESTS.length >= 1) {
runClosureCompiler({
'-jar' : COMPILER,
'--charset' : ENCODING,
'--compilation_level' : 'WHITESPACE_ONLY',
'--js_output_file' : DEST_TEST,
'--js' : getFileNames(FOLDER_TESTS),
'--formatting' : [
'pretty_print',
'print_input_delimiter'
]
});
}
} catch (e) {
WScript.Echo(e.command);
WScript.Echo(e.errorMessage);
}