mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-08 10:17:48 +00:00
Add --source-map build option. [closes #161]
Former-commit-id: e0cac11fda86671d944de5c157d3df3146d6def1
This commit is contained in:
15
README.md
15
README.md
@@ -154,13 +154,14 @@ Unless specified by `-o` or `--output`, all files created are saved to the curre
|
|||||||
|
|
||||||
The following options are also supported:
|
The following options are also supported:
|
||||||
|
|
||||||
* `-c`, `--stdout` Write output to standard output
|
* `-c`, `--stdout` Write output to standard output
|
||||||
* `-d`, `--debug` Write only the debug output
|
* `-d`, `--debug` Write only the debug output
|
||||||
* `-h`, `--help` Display help information
|
* `-h`, `--help` Display help information
|
||||||
* `-m`, `--minify` Write only the minified output
|
* `-m`, `--minify` Write only the minified output
|
||||||
* `-o`, `--output` Write output to a given path/filename
|
* `-o`, `--output` Write output to a given path/filename
|
||||||
* `-s`, `--silent` Skip status updates normally logged to the console
|
* `-p`, `--source-map` Generate a source map for the minified output
|
||||||
* `-V`, `--version` Output current version of Lo-Dash
|
* `-s`, `--silent` Skip status updates normally logged to the console
|
||||||
|
* `-V`, `--version` Output current version of Lo-Dash
|
||||||
|
|
||||||
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
||||||
|
|
||||||
|
|||||||
61
build.js
61
build.js
@@ -580,13 +580,14 @@
|
|||||||
'',
|
'',
|
||||||
' Options:',
|
' Options:',
|
||||||
'',
|
'',
|
||||||
' -c, --stdout Write output to standard output',
|
' -c, --stdout Write output to standard output',
|
||||||
' -d, --debug Write only the debug output',
|
' -d, --debug Write only the debug output',
|
||||||
' -h, --help Display help information',
|
' -h, --help Display help information',
|
||||||
' -m, --minify Write only the minified output',
|
' -m, --minify Write only the minified output',
|
||||||
' -o, --output Write output to a given path/filename',
|
' -o, --output Write output to a given path/filename',
|
||||||
' -s, --silent Skip status updates normally logged to the console',
|
' -p, --source-map Generate a source map for the minified output',
|
||||||
' -V, --version Output current version of Lo-Dash',
|
' -s, --silent Skip status updates normally logged to the console',
|
||||||
|
' -V, --version Output current version of Lo-Dash',
|
||||||
''
|
''
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
}
|
}
|
||||||
@@ -1182,7 +1183,7 @@
|
|||||||
// used to report invalid command-line arguments
|
// used to report invalid command-line arguments
|
||||||
var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
|
var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
|
||||||
if (/^(?:-o|--output)$/.test(options[index - 1]) ||
|
if (/^(?:-o|--output)$/.test(options[index - 1]) ||
|
||||||
/^(?:category|exclude|exports|iife|include|moduleId|minus|plus|settings|template)=.*$/i.test(value)) {
|
/^(?:category|exclude|exports|iife|include|moduleId|minus|plus|settings|template)=.*$/.test(value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
@@ -1198,6 +1199,7 @@
|
|||||||
'-h', '--help',
|
'-h', '--help',
|
||||||
'-m', '--minify',
|
'-m', '--minify',
|
||||||
'-o', '--output',
|
'-o', '--output',
|
||||||
|
'-p', '--source-map',
|
||||||
'-s', '--silent',
|
'-s', '--silent',
|
||||||
'-V', '--version'
|
'-V', '--version'
|
||||||
].indexOf(value) > -1;
|
].indexOf(value) > -1;
|
||||||
@@ -1241,6 +1243,9 @@
|
|||||||
return match ? match[1] : result;
|
return match ? match[1] : result;
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
|
// the path to the source file
|
||||||
|
var filePath = path.join(__dirname, 'lodash.js');
|
||||||
|
|
||||||
// flag used to specify a Backbone build
|
// flag used to specify a Backbone build
|
||||||
var isBackbone = options.indexOf('backbone') > -1;
|
var isBackbone = options.indexOf('backbone') > -1;
|
||||||
|
|
||||||
@@ -1256,8 +1261,11 @@
|
|||||||
// flag used to specify an Underscore build
|
// flag used to specify an Underscore build
|
||||||
var isUnderscore = options.indexOf('underscore') > -1;
|
var isUnderscore = options.indexOf('underscore') > -1;
|
||||||
|
|
||||||
|
// flag used to specify creating a source map for the minified source
|
||||||
|
var isMapped = options.indexOf('-p') > -1 || options.indexOf('--source-map') > -1;
|
||||||
|
|
||||||
// flag used to specify only creating the minified build
|
// flag used to specify only creating the minified build
|
||||||
var isMinify = !isDebug && options.indexOf('-m') > -1 || options.indexOf('--minify')> -1;
|
var isMinify = options.indexOf('-m') > -1 || options.indexOf('--minify') > -1;
|
||||||
|
|
||||||
// flag used to specify a mobile build
|
// flag used to specify a mobile build
|
||||||
var isMobile = !isLegacy && (isCSP || isUnderscore || options.indexOf('mobile') > -1);
|
var isMobile = !isLegacy && (isCSP || isUnderscore || options.indexOf('mobile') > -1);
|
||||||
@@ -1325,7 +1333,7 @@
|
|||||||
var isTemplate = !!templatePattern;
|
var isTemplate = !!templatePattern;
|
||||||
|
|
||||||
// the lodash.js source
|
// the lodash.js source
|
||||||
var source = fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8');
|
var source = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
// flag used to specify replacing Lo-Dash's `_.clone` with Underscore's
|
// flag used to specify replacing Lo-Dash's `_.clone` with Underscore's
|
||||||
var useUnderscoreClone = isUnderscore;
|
var useUnderscoreClone = isUnderscore;
|
||||||
@@ -2123,7 +2131,7 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// used to specify creating a custom build
|
// used to specify creating a custom build
|
||||||
var isCustom = isBackbone || isLegacy || isMobile || isStrict || isUnderscore ||
|
var isCustom = isBackbone || isLegacy || isMapped || isMobile || isStrict || isUnderscore ||
|
||||||
/(?:category|exclude|exports|iife|include|minus|plus)=/.test(options) ||
|
/(?:category|exclude|exports|iife|include|minus|plus)=/.test(options) ||
|
||||||
!_.isEqual(exportsOptions, exportsAll);
|
!_.isEqual(exportsOptions, exportsAll);
|
||||||
|
|
||||||
@@ -2144,7 +2152,10 @@
|
|||||||
stdout.write(debugSource);
|
stdout.write(debugSource);
|
||||||
callback(debugSource);
|
callback(debugSource);
|
||||||
} else if (!isStdOut) {
|
} else if (!isStdOut) {
|
||||||
callback(debugSource, (isDebug && outputPath) || path.join(cwd, basename + '.js'));
|
callback({
|
||||||
|
'source': debugSource,
|
||||||
|
'outputPath': (isDebug && outputPath) || path.join(cwd, basename + '.js')
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// begin the minification process
|
// begin the minification process
|
||||||
@@ -2152,22 +2163,24 @@
|
|||||||
outputPath || (outputPath = path.join(cwd, basename + '.min.js'));
|
outputPath || (outputPath = path.join(cwd, basename + '.min.js'));
|
||||||
|
|
||||||
minify(source, {
|
minify(source, {
|
||||||
|
'filePath': filePath,
|
||||||
|
'isMapped': isMapped,
|
||||||
'isSilent': isSilent,
|
'isSilent': isSilent,
|
||||||
'isTemplate': isTemplate,
|
'isTemplate': isTemplate,
|
||||||
'outputPath': outputPath,
|
'outputPath': outputPath,
|
||||||
'onComplete': function(source) {
|
'onComplete': function(data) {
|
||||||
// inject "use strict" directive
|
// inject "use strict" directive
|
||||||
if (isStrict) {
|
if (isStrict) {
|
||||||
source = source.replace(/^([\s\S]*?function[^{]+{)([^"'])/, '$1"use strict";$2');
|
data.source = data.source.replace(/^([\s\S]*?function[^{]+{)([^"'])/, '$1"use strict";$2');
|
||||||
}
|
}
|
||||||
if (isCustom) {
|
if (isCustom) {
|
||||||
source = addCommandsToHeader(source, options);
|
data.source = addCommandsToHeader(data.source, options);
|
||||||
}
|
}
|
||||||
if (isStdOut) {
|
if (isStdOut) {
|
||||||
stdout.write(source);
|
stdout.write(data.source);
|
||||||
callback(source);
|
callback(data);
|
||||||
} else {
|
} else {
|
||||||
callback(source, outputPath);
|
callback(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2182,8 +2195,16 @@
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// or invoked directly
|
// or invoked directly
|
||||||
build(process.argv, function(source, filePath) {
|
build(process.argv, function(data) {
|
||||||
filePath && fs.writeFileSync(filePath, source, 'utf8');
|
var outputPath = data.outputPath,
|
||||||
|
sourceMap = data.sourceMap;
|
||||||
|
|
||||||
|
if (outputPath) {
|
||||||
|
fs.writeFileSync(outputPath, data.source, 'utf8');
|
||||||
|
if (sourceMap) {
|
||||||
|
fs.writeFileSync(path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map'), sourceMap, 'utf8');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|||||||
106
build/minify.js
106
build/minify.js
@@ -89,6 +89,7 @@
|
|||||||
options = source;
|
options = source;
|
||||||
|
|
||||||
var filePath = options[options.length - 1],
|
var filePath = options[options.length - 1],
|
||||||
|
isMapped = options.indexOf('-p') > -1 || options.indexOf('--source-map') > -1,
|
||||||
isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1,
|
isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1,
|
||||||
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
|
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
|
||||||
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
|
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
|
||||||
@@ -102,6 +103,8 @@
|
|||||||
}, outputPath);
|
}, outputPath);
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
'filePath': filePath,
|
||||||
|
'isMapped': isMapped,
|
||||||
'isSilent': isSilent,
|
'isSilent': isSilent,
|
||||||
'isTemplate': isTemplate,
|
'isTemplate': isTemplate,
|
||||||
'outputPath': outputPath
|
'outputPath': outputPath
|
||||||
@@ -157,6 +160,8 @@
|
|||||||
this.hybrid = { 'simple': {}, 'advanced': {} };
|
this.hybrid = { 'simple': {}, 'advanced': {} };
|
||||||
this.uglified = {};
|
this.uglified = {};
|
||||||
|
|
||||||
|
this.filePath = options.filePath;
|
||||||
|
this.isMapped = !!options.isMapped;
|
||||||
this.isSilent = !!options.isSilent;
|
this.isSilent = !!options.isSilent;
|
||||||
this.isTemplate = !!options.isTemplate;
|
this.isTemplate = !!options.isTemplate;
|
||||||
this.outputPath = options.outputPath;
|
this.outputPath = options.outputPath;
|
||||||
@@ -164,8 +169,14 @@
|
|||||||
source = preprocess(source, options);
|
source = preprocess(source, options);
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
|
||||||
this.onComplete = options.onComplete || function(source) {
|
this.onComplete = options.onComplete || function(data) {
|
||||||
fs.writeFileSync(this.outputPath, source, 'utf8');
|
var outputPath = this.outputPath,
|
||||||
|
sourceMap = data.sourceMap;
|
||||||
|
|
||||||
|
fs.writeFileSync(outputPath, data.source, 'utf8');
|
||||||
|
if (sourceMap) {
|
||||||
|
fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// begin the minification process
|
// begin the minification process
|
||||||
@@ -182,8 +193,7 @@
|
|||||||
* @private
|
* @private
|
||||||
* @param {Object} options The options object.
|
* @param {Object} options The options object.
|
||||||
* id - The Git object ID of the `.tar.gz` file.
|
* id - The Git object ID of the `.tar.gz` file.
|
||||||
* onComplete - The function, invoked with one argument (exception),
|
* onComplete - The function called once the extraction has finished.
|
||||||
* called once the extraction has finished.
|
|
||||||
* path - The path of the extraction directory.
|
* path - The path of the extraction directory.
|
||||||
* title - The dependency's title used in status updates logged to the console.
|
* title - The dependency's title used in status updates logged to the console.
|
||||||
*/
|
*/
|
||||||
@@ -242,6 +252,17 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the source map path from the given output path.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} outputPath The output path.
|
||||||
|
* @returns {String} Returns the source map path.
|
||||||
|
*/
|
||||||
|
function getMapPath(outputPath) {
|
||||||
|
return path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map');
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,17 +275,26 @@
|
|||||||
* @param {Function} callback The function called once the process has completed.
|
* @param {Function} callback The function called once the process has completed.
|
||||||
*/
|
*/
|
||||||
function closureCompile(source, mode, callback) {
|
function closureCompile(source, mode, callback) {
|
||||||
|
var filePath = this.filePath,
|
||||||
|
outputPath = this.outputPath,
|
||||||
|
isMapped = this.isMapped,
|
||||||
|
mapPath = getMapPath(outputPath),
|
||||||
|
options = closureOptions.slice();
|
||||||
|
|
||||||
// use simple optimizations when minifying template files
|
// use simple optimizations when minifying template files
|
||||||
var options = closureOptions.slice();
|
|
||||||
options.push('--compilation_level=' + optimizationModes[this.isTemplate ? 'simple' : mode]);
|
options.push('--compilation_level=' + optimizationModes[this.isTemplate ? 'simple' : mode]);
|
||||||
|
|
||||||
|
if (isMapped) {
|
||||||
|
options.push('--create_source_map=' + mapPath, '--source_map_format=V3');
|
||||||
|
}
|
||||||
|
|
||||||
// the standard error stream, standard output stream, and the Closure Compiler process
|
// the standard error stream, standard output stream, and the Closure Compiler process
|
||||||
var error = '',
|
var error = '',
|
||||||
output = '',
|
output = '',
|
||||||
compiler = spawn('java', ['-jar', closurePath].concat(options));
|
compiler = spawn('java', ['-jar', closurePath].concat(options));
|
||||||
|
|
||||||
if (!this.isSilent) {
|
if (!this.isSilent) {
|
||||||
console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
|
console.log('Compressing ' + path.basename(outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
|
||||||
}
|
}
|
||||||
compiler.stdout.on('data', function(data) {
|
compiler.stdout.on('data', function(data) {
|
||||||
// append the data to the output stream
|
// append the data to the output stream
|
||||||
@@ -282,7 +312,18 @@
|
|||||||
var exception = new Error(error);
|
var exception = new Error(error);
|
||||||
exception.status = status;
|
exception.status = status;
|
||||||
}
|
}
|
||||||
callback(exception, output);
|
if (isMapped) {
|
||||||
|
var mapOutput = fs.readFileSync(mapPath, 'utf8');
|
||||||
|
fs.unlinkSync(mapPath);
|
||||||
|
|
||||||
|
output = output
|
||||||
|
.replace(/[\s;]*$/, '\n//@ sourceMappingURL=' + path.basename(mapPath));
|
||||||
|
|
||||||
|
mapOutput = mapOutput
|
||||||
|
.replace(/("file":)""/, '$1"' + path.basename(outputPath) + '"')
|
||||||
|
.replace(/("sources":)\["stdin"\]/, '$1["' + path.basename(filePath) + '"]');
|
||||||
|
}
|
||||||
|
callback(exception, output, mapOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
// proxy the standard input to the Closure Compiler
|
// proxy the standard input to the Closure Compiler
|
||||||
@@ -350,13 +391,17 @@
|
|||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
* @param {String} result The resulting minified source.
|
* @param {String} result The resulting minified source.
|
||||||
|
* @param {String} map The source map output.
|
||||||
*/
|
*/
|
||||||
function onClosureSimpleCompile(exception, result) {
|
function onClosureSimpleCompile(exception, result, map) {
|
||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
result = postprocess(result);
|
result = postprocess(result);
|
||||||
this.compiled.simple.source = result;
|
|
||||||
|
var simple = this.compiled.simple;
|
||||||
|
simple.source = result;
|
||||||
|
simple.sourceMap = map;
|
||||||
zlib.gzip(result, onClosureSimpleGzip.bind(this));
|
zlib.gzip(result, onClosureSimpleGzip.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,13 +431,17 @@
|
|||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
* @param {String} result The resulting minified source.
|
* @param {String} result The resulting minified source.
|
||||||
|
* @param {String} map The source map output.
|
||||||
*/
|
*/
|
||||||
function onClosureAdvancedCompile(exception, result) {
|
function onClosureAdvancedCompile(exception, result, map) {
|
||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
result = postprocess(result);
|
result = postprocess(result);
|
||||||
this.compiled.advanced.source = result;
|
|
||||||
|
var advanced = this.compiled.advanced;
|
||||||
|
advanced.source = result;
|
||||||
|
advanced.sourceMap = map;
|
||||||
zlib.gzip(result, onClosureAdvancedGzip.bind(this));
|
zlib.gzip(result, onClosureAdvancedGzip.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,8 +461,14 @@
|
|||||||
}
|
}
|
||||||
this.compiled.advanced.gzip = result;
|
this.compiled.advanced.gzip = result;
|
||||||
|
|
||||||
// next, minify the source using only UglifyJS
|
// if mapped, finish by choosing the smallest compressed file
|
||||||
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
|
if (this.isMapped) {
|
||||||
|
onComplete.call(this);
|
||||||
|
}
|
||||||
|
// else, minify the source using UglifyJS
|
||||||
|
else {
|
||||||
|
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -538,18 +593,25 @@
|
|||||||
|
|
||||||
// select the smallest gzipped file and use its minified counterpart as the
|
// select the smallest gzipped file and use its minified counterpart as the
|
||||||
// official minified release (ties go to the Closure Compiler)
|
// official minified release (ties go to the Closure Compiler)
|
||||||
var min = Math.min(
|
var min = this.isMapped
|
||||||
compiledSimple.gzip.length,
|
? Math.min(
|
||||||
compiledAdvanced.gzip.length,
|
compiledSimple.gzip.length,
|
||||||
uglified.gzip.length,
|
compiledAdvanced.gzip.length
|
||||||
hybridSimple.gzip.length,
|
)
|
||||||
hybridAdvanced.gzip.length
|
: Math.min(
|
||||||
);
|
compiledSimple.gzip.length,
|
||||||
|
compiledAdvanced.gzip.length,
|
||||||
|
uglified.gzip.length,
|
||||||
|
hybridSimple.gzip.length,
|
||||||
|
hybridAdvanced.gzip.length
|
||||||
|
);
|
||||||
|
|
||||||
// pass the minified source to the "onComplete" callback
|
// pass the minified source to the "onComplete" callback
|
||||||
[compiledSimple, compiledAdvanced, uglified, hybridSimple, hybridAdvanced].some(function(data) {
|
[compiledSimple, compiledAdvanced, uglified, hybridSimple, hybridAdvanced].some(function(data) {
|
||||||
if (data.gzip.length == min) {
|
var gzip = data.gzip;
|
||||||
this.onComplete(data.source);
|
if (gzip && gzip.length == min) {
|
||||||
|
data.outputPath = this.outputPath;
|
||||||
|
this.onComplete(data);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
// add trailing semicolon
|
// add trailing semicolon
|
||||||
if (source) {
|
if (source) {
|
||||||
source = source.replace(/[\s;]*$/, ';');
|
source = source.replace(/[\s;]*(\n\/\/.+)?$/, ';$1');
|
||||||
}
|
}
|
||||||
// exit early if version snippet isn't found
|
// exit early if version snippet isn't found
|
||||||
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
|
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
|
||||||
|
|||||||
Reference in New Issue
Block a user