From 292b0bbe490ac71d80bd6ac616d35beb7f6ea1e3 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Mon, 23 Apr 2012 13:29:43 -0600 Subject: [PATCH 1/4] `build.js`: Automatically save the smallest minified distribution as `lodash.min.js`. Former-commit-id: 1cbfa78f89a42f8f9dbe72a90adc4abeb2de3cb3 --- build.js | 93 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/build.js b/build.js index 5b8430707..f9d5dcffc 100755 --- a/build.js +++ b/build.js @@ -107,35 +107,6 @@ compressor.stdin.end(source); } - /** - * Compresses a `source` string using UglifyJS. Yields the result to a - * `callback` function. This function is synchronous; the `callback` is used - * for symmetry. - * - * @private - * @param {String} source The JavaScript source to minify. - * @param {Function} callback The function called when minifying is complete. - */ - function uglify(source, callback) { - var ugly = uglifyJS.uglify; - - var result = ugly.gen_code( - // enable unsafe transformations. - ugly.ast_squeeze_more( - ugly.ast_squeeze( - // munge variable and function names, excluding the special `define` - // function exposed by AMD loaders. - ugly.ast_mangle(uglifyJS.parser.parse(source), { - 'except': ['define'] - } - ))), { - 'ascii_only': true - }); - - // split lines at 500 characters to be consistent with Closure Compiler - callback(ugly.split_lines(result, 500)); - } - /*--------------------------------------------------------------------------*/ // create the destination directory if it doesn't exist @@ -144,35 +115,63 @@ } // compress and `gzip` Lo-Dash using the Closure Compiler - compile(source, function(exception, result) { + compile(source, function(exception, compiledSource) { if (exception) { throw exception; } - // post-process the minified source - var source = postprocess(result); - // save the final minified version - fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), source); + // post-process the compiled source + compiledSource = postprocess(compiledSource); - // save the `gzip`-ed version - gzip(source, function(exception, result) { + // save the final compiled version + fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), compiledSource); + + // `gzip` the compiled version + gzip(compiledSource, function gzipCompiled(exception, result) { if (exception) { throw exception; } + + // record the size of the compiled version + var compiledSize = result.length; + // explicit `binary` encoding is necessary to ensure that the stream is written correctly fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), result, 'binary'); - }); - }); - // compress and `gzip` Lo-Dash using UglifyJS - uglify(source, function(result) { - var source = postprocess(result); - fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), source); - gzip(source, function(exception, result) { - if (exception) { - throw exception; - } - fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), result, 'binary'); + // compress Lo-Dash using UglifyJS + var ugly = uglifyJS.uglify, + uglifiedSource = ugly.gen_code( + // enable unsafe transformations + ugly.ast_squeeze_more( + ugly.ast_squeeze( + // munge variable and function names, excluding the special `define` + // function exposed by AMD loaders + ugly.ast_mangle(uglifyJS.parser.parse(source), { + 'except': ['define'] + } + ))), { + 'ascii_only': true + }); + + // post-process the uglified source and split lines at 500 characters for + // consistency with Closure Compiler + uglifiedSource = postprocess(ugly.split_lines(uglifiedSource, 500)); + + // save the uglified version + fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), uglifiedSource); + + // `gzip` the uglified version + gzip(uglifiedSource, function gzipUglified(exception, result) { + if (exception) { + throw exception; + } + var uglifiedSize = result.length; + fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), result, 'binary'); + + // select the smallest minified distribution and use it as the official + // minified release + fs.writeFileSync(path.join(__dirname, "lodash.min.js"), compiledSize < uglifiedSize ? compiledSource : uglifiedSource); + }); }); }); }()); From bd70d31a7236bc476bafa1033983b9aba58f2150 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Mon, 23 Apr 2012 13:34:38 -0600 Subject: [PATCH 2/4] `build.js`: Print compression status messages to the console. Former-commit-id: 07524fbba01e45f0e51f24b61081527e59cb0006 --- build.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.js b/build.js index f9d5dcffc..7f8b53781 100755 --- a/build.js +++ b/build.js @@ -120,6 +120,8 @@ throw exception; } + console.log("Compressing Lodash using the Closure Compiler..."); + // post-process the compiled source compiledSource = postprocess(compiledSource); @@ -138,6 +140,8 @@ // explicit `binary` encoding is necessary to ensure that the stream is written correctly fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), result, 'binary'); + console.log("Done. Size: %d KB.", compiledSize); + // compress Lo-Dash using UglifyJS var ugly = uglifyJS.uglify, uglifiedSource = ugly.gen_code( @@ -153,6 +157,8 @@ 'ascii_only': true }); + console.log("Compressing Lodash using UglifyJS..."); + // post-process the uglified source and split lines at 500 characters for // consistency with Closure Compiler uglifiedSource = postprocess(ugly.split_lines(uglifiedSource, 500)); @@ -168,6 +174,8 @@ var uglifiedSize = result.length; fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), result, 'binary'); + console.log("Done. Size: %d KB.", uglifiedSize); + // select the smallest minified distribution and use it as the official // minified release fs.writeFileSync(path.join(__dirname, "lodash.min.js"), compiledSize < uglifiedSize ? compiledSource : uglifiedSource); From 2f91764f80388c20296abed791ab74bec575e4a6 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Mon, 23 Apr 2012 16:41:04 -0600 Subject: [PATCH 3/4] Clean up `build.js`. The build process now delays writing the compressed and `gzip`-ped versions to disk until all build stages have finished successfully. Former-commit-id: 498165a725e8b1023b05d2a737fdac6d6a8c46ea --- build.js | 183 ++++++++++++++++++++++--------------------------------- 1 file changed, 74 insertions(+), 109 deletions(-) diff --git a/build.js b/build.js index 7f8b53781..8bdfb05c6 100755 --- a/build.js +++ b/build.js @@ -26,85 +26,52 @@ /*--------------------------------------------------------------------------*/ /** - * Compresses a `source` string using the Closure Compiler. Yields the - * minified result, and any exceptions encountered, to a `callback` function. + * Invokes a process with the given `name`, `parameters`, and `source` (used as + * the standard input). Yields the result to a `callback` function. The optional + * `encoding` argument specifies the output stream encoding. * * @private - * @param {String} source The JavaScript source to minify. - * @param {Function} callback The function called when minifying is complete. + * @param {String} name The name of the process. + * @param {Array} parameters An array of arguments to proxy to the process. + * @param {String} source The standard input to proxy to the process. + * @param {String} [encoding] The expected encoding of the output stream. + * @param {Function} callback The function to call once the process completes. */ - function compile(source, callback) { - var stderr = '', - stdout = ''; + function invoke(name, parameters, source, encoding, callback) { + // the process instance and its standard output and error streams + var process = spawn(name, parameters), + results = '', error = ''; - var compiler = spawn('java', [ - // load the Closure Compiler and set the compression options - '-jar', path.join(__dirname, 'vendor', 'closure-compiler', 'compiler.jar'), - '--compilation_level=ADVANCED_OPTIMIZATIONS', - '--language_in=ECMASCRIPT5_STRICT', - '--warning_level=QUIET' - ]); + if (typeof encoding == 'string' && callback != null) { + // explicitly set the encoding of the output stream if one is specified + process.stdout.setEncoding(encoding); + } else { + callback = encoding; + encoding = null; + } - // explicitly set the encoding of the output and error streams - compiler.stdout.setEncoding('utf8'); - compiler.stderr.setEncoding('utf8'); - - compiler.stdout.on('data', function(data) { - stdout += data; + process.stdout.on('data', function onData(data) { + // append the compiled source to the output stream + results += data; }); - compiler.stderr.on('data', function(data) { - stderr += data; + process.stderr.on('data', function onError(data) { + // append the error message to the error stream + error += data; }); - compiler.on('exit', function(status) { + process.on('exit', function onExit(status) { var exception = null; + // `status` contains the process exit code if (status) { - exception = new Error(stderr); + exception = new Error(error); exception.status = status; } - callback(exception, stdout); + callback(exception, results); }); - // proxy the source string to Closure Compiler - compiler.stdin.end(source); - } - - /** - * Compresses a `source` string using the Unix `gzip` commands. Yields the - * result, and any exceptions encountered, to a `callback` function. - * - * @private - * @param {String} source The JavaScript source to gzip. - * @param {Function} callback The function called when gzipping is complete. - */ - function gzip(source, callback) { - var compressor = spawn('gzip', ['-9f', '-c']), - stderr = '', - stdout = ''; - - compressor.stdout.setEncoding('binary'); - compressor.stderr.setEncoding('utf8'); - - compressor.stdout.on('data', function(data) { - stdout += data; - }); - - compressor.stderr.on('data', function(data) { - stderr += data; - }); - - compressor.on('exit', function(status) { - var exception = null; - if (status) { - exception = new Error(stderr); - exception.status = status; - } - callback(exception, stdout); - }); - - // proxy the source string to the `gzip` executable - compressor.stdin.end(source); + // proxy the standard input to the process + process.stdin.end(source); } /*--------------------------------------------------------------------------*/ @@ -115,70 +82,68 @@ } // compress and `gzip` Lo-Dash using the Closure Compiler - compile(source, function(exception, compiledSource) { + console.log('Compressing Lodash using the Closure Compiler...'); + invoke('java', ['-jar', path.join(__dirname, 'vendor', 'closure-compiler', 'compiler.jar'), '--compilation_level=ADVANCED_OPTIMIZATIONS', '--language_in=ECMASCRIPT5_STRICT', '--warning_level=QUIET'], source, function onClosureCompile(exception, compiledSource) { if (exception) { throw exception; } - console.log("Compressing Lodash using the Closure Compiler..."); - - // post-process the compiled source + // post-process and `gzip` the compiled distribution compiledSource = postprocess(compiledSource); - - // save the final compiled version - fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), compiledSource); - - // `gzip` the compiled version - gzip(compiledSource, function gzipCompiled(exception, result) { + invoke('gzip', ['-9f', '-c'], compiledSource, 'binary', function onClosureCompress(exception, compiledGzippedSource) { + var compiledSize, ugly, uglifiedSource; if (exception) { throw exception; } - // record the size of the compiled version - var compiledSize = result.length; - - // explicit `binary` encoding is necessary to ensure that the stream is written correctly - fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), result, 'binary'); - - console.log("Done. Size: %d KB.", compiledSize); + // store and print the `gzip`-ped size of the compiled distribution + compiledSize = compiledGzippedSource.length; + console.log('Done. Size: %d KB.', compiledSize); // compress Lo-Dash using UglifyJS - var ugly = uglifyJS.uglify, - uglifiedSource = ugly.gen_code( - // enable unsafe transformations - ugly.ast_squeeze_more( - ugly.ast_squeeze( - // munge variable and function names, excluding the special `define` - // function exposed by AMD loaders - ugly.ast_mangle(uglifyJS.parser.parse(source), { - 'except': ['define'] - } - ))), { - 'ascii_only': true - }); + console.log('Compressing Lodash using UglifyJS...'); + ugly = uglifyJS.uglify; - console.log("Compressing Lodash using UglifyJS..."); + uglifiedSource = ugly.gen_code( + // enable unsafe transformations + ugly.ast_squeeze_more( + ugly.ast_squeeze( + // munge variable and function names, excluding the special `define` + // function exposed by AMD loaders + ugly.ast_mangle(uglifyJS.parser.parse(source), { + 'except': ['define'] + } + ))), { + 'ascii_only': true + }); - // post-process the uglified source and split lines at 500 characters for - // consistency with Closure Compiler + // post-process and `gzip` the uglified distribution. Lines are + // restricted to 500 characters for consistency with Closure Compiler. uglifiedSource = postprocess(ugly.split_lines(uglifiedSource, 500)); - - // save the uglified version - fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), uglifiedSource); - - // `gzip` the uglified version - gzip(uglifiedSource, function gzipUglified(exception, result) { + invoke('gzip', ['-9f', '-c'], uglifiedSource, 'binary', function onUglifyCompress(exception, uglifiedGzippedSource) { + var uglifiedSize; if (exception) { throw exception; } - var uglifiedSize = result.length; - fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), result, 'binary'); - console.log("Done. Size: %d KB.", uglifiedSize); + // store and print the `gzip`-ped size of the uglified distribution + uglifiedSize = uglifiedGzippedSource.length; + console.log('Done. Size: %d KB.', uglifiedSize); - // select the smallest minified distribution and use it as the official - // minified release - fs.writeFileSync(path.join(__dirname, "lodash.min.js"), compiledSize < uglifiedSize ? compiledSource : uglifiedSource); + // save the compiled version to disk. The explicit `binary` + // encoding for the `gzip`-ped version is necessary to ensure that + // the stream is written correctly. + fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), compiledSource); + fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), compiledGzippedSource, 'binary'); + + // save the uglified version to disk. + fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), uglifiedSource); + fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), uglifiedGzippedSource, 'binary'); + + // select the smallest minified distribution and use it as the + // official minified release. If they are equivalent, the compiled + // distribution is used. + fs.writeFileSync(path.join(__dirname, 'lodash.min.js'), compiledSize < uglifiedSize ? compiledSource : uglifiedSource); }); }); }); From 0d77d292e50a153f5b5c5f7da8fc025a5223b7b6 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Mon, 23 Apr 2012 16:47:00 -0600 Subject: [PATCH 4/4] Comment style consistency. Former-commit-id: c166fbd838f2ad139bb89da2c916fa07c4fceff0 --- build.js | 8 ++++---- build/post-compile.js | 4 ++-- build/pre-compile.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.js b/build.js index 8bdfb05c6..ee65def5d 100755 --- a/build.js +++ b/build.js @@ -118,7 +118,7 @@ }); // post-process and `gzip` the uglified distribution. Lines are - // restricted to 500 characters for consistency with Closure Compiler. + // restricted to 500 characters for consistency with Closure Compiler uglifiedSource = postprocess(ugly.split_lines(uglifiedSource, 500)); invoke('gzip', ['-9f', '-c'], uglifiedSource, 'binary', function onUglifyCompress(exception, uglifiedGzippedSource) { var uglifiedSize; @@ -132,17 +132,17 @@ // save the compiled version to disk. The explicit `binary` // encoding for the `gzip`-ped version is necessary to ensure that - // the stream is written correctly. + // the stream is written correctly fs.writeFileSync(path.join(distPath, 'lodash.compiler.js'), compiledSource); fs.writeFileSync(path.join(distPath, 'lodash.compiler.js.gz'), compiledGzippedSource, 'binary'); - // save the uglified version to disk. + // save the uglified version to disk fs.writeFileSync(path.join(distPath, 'lodash.uglify.js'), uglifiedSource); fs.writeFileSync(path.join(distPath, 'lodash.uglify.js.gz'), uglifiedGzippedSource, 'binary'); // select the smallest minified distribution and use it as the // official minified release. If they are equivalent, the compiled - // distribution is used. + // distribution is used fs.writeFileSync(path.join(__dirname, 'lodash.min.js'), compiledSize < uglifiedSize ? compiledSource : uglifiedSource); }); }); diff --git a/build/post-compile.js b/build/post-compile.js index 2b8829421..1f33a3315 100644 --- a/build/post-compile.js +++ b/build/post-compile.js @@ -39,9 +39,9 @@ if (module != require.main) { module.exports = postprocess; } else { - // Read the JavaScript source file from the first argument if the script + // read the JavaScript source file from the first argument if the script // was invoked directly (e.g. `node post-compile.js source.js`) and write to - // the same file. + // the same file (function() { var source = fs.readFileSync(process.argv[2], 'utf8'); fs.writeFileSync(process.argv[2], postprocess(source), 'utf8'); diff --git a/build/pre-compile.js b/build/pre-compile.js index abe1380f8..96352dbf1 100644 --- a/build/pre-compile.js +++ b/build/pre-compile.js @@ -199,9 +199,9 @@ if (module != require.main) { module.exports = preprocess; } else { - // Read the JavaScript source file from the first argument if the script + // read the JavaScript source file from the first argument if the script // was invoked directly (e.g. `node pre-compile.js source.js`) and write to - // the same file. + // the same file (function() { var source = fs.readFileSync(process.argv[2], 'utf8'); fs.writeFileSync(process.argv[2], preprocess(source), 'utf8');