From 53eced6be061f0505a6f2386383b60a7009f2191 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Thu, 25 May 2017 01:33:04 -0600
Subject: [PATCH] uglify-js@3, JS source maps :cake:
---
package.json | 2 +-
src/meta/js.js | 26 +++++---
src/meta/minifier.js | 145 ++++++++++++++++++++++++++-----------------
test/build.js | 56 +++++++++++------
4 files changed, 145 insertions(+), 84 deletions(-)
diff --git a/package.json b/package.json
index 7d7bacd4d9..c8a988b62f 100644
--- a/package.json
+++ b/package.json
@@ -92,7 +92,7 @@
"string": "^3.0.0",
"templates.js": "0.3.10",
"toobusy-js": "^0.5.1",
- "uglify-js": "^2.6.0",
+ "uglify-js": "^3.0.11",
"underscore": "^1.8.3",
"underscore.deep": "^0.5.1",
"validator": "7.0.0",
diff --git a/src/meta/js.js b/src/meta/js.js
index d0399c70c1..4858f69bf5 100644
--- a/src/meta/js.js
+++ b/src/meta/js.js
@@ -88,6 +88,8 @@ module.exports = function (Meta) {
},
};
+ var basePath = path.resolve(__dirname, '../..');
+
function minifyModules(modules, fork, callback) {
var moduleDirs = modules.reduce(function (prev, mod) {
var dir = path.resolve(path.dirname(mod.destPath));
@@ -201,7 +203,10 @@ module.exports = function (Meta) {
};
});
- moduleFiles = moduleFiles.concat(mods);
+ moduleFiles = moduleFiles.concat(mods).map(function (mod) {
+ mod.filename = path.relative(basePath, mod.srcPath).replace(/\\/g, '/');
+ return mod;
+ });
next();
});
@@ -287,8 +292,6 @@ module.exports = function (Meta) {
return callback(err);
}
- var basePath = path.resolve(__dirname, '../..');
-
var scripts = Meta.js.scripts.base.concat(pluginScripts);
if (target === 'client' && global.env !== 'development') {
@@ -296,7 +299,11 @@ module.exports = function (Meta) {
}
scripts = scripts.map(function (script) {
- return path.resolve(basePath, script).replace(/\\/g, '/');
+ var srcPath = path.resolve(basePath, script).replace(/\\/g, '/');
+ return {
+ srcPath: srcPath,
+ filename: path.relative(basePath, srcPath).replace(/\\/g, '/'),
+ };
});
callback(null, scripts);
@@ -315,12 +322,13 @@ module.exports = function (Meta) {
},
function (files, next) {
var minify = global.env !== 'development';
-
- minifier.js.bundle(files, minify, fork, next);
- },
- function (bundle, next) {
var filePath = path.join(__dirname, '../../build/public', fileNames[target]);
- fs.writeFile(filePath, bundle.code, next);
+
+ minifier.js.bundle({
+ files: files,
+ filename: fileNames[target],
+ destPath: filePath,
+ }, minify, fork, next);
},
], callback);
};
diff --git a/src/meta/minifier.js b/src/meta/minifier.js
index 07f33d8253..5e78203c26 100644
--- a/src/meta/minifier.js
+++ b/src/meta/minifier.js
@@ -1,18 +1,16 @@
'use strict';
-var uglifyjs = require('uglify-js');
-var async = require('async');
var fs = require('fs');
var childProcess = require('child_process');
var os = require('os');
+var uglifyjs = require('uglify-js');
+var async = require('async');
var winston = require('winston');
var less = require('less');
var postcss = require('postcss');
var autoprefixer = require('autoprefixer');
var clean = require('postcss-clean');
-var file = require('../file');
-
var Minifier = module.exports;
function setupDebugging() {
@@ -163,13 +161,21 @@ function executeAction(action, fork, callback) {
function concat(data, callback) {
if (data.files && data.files.length) {
- async.mapLimit(data.files, 1000, fs.readFile, function (err, files) {
+ async.mapLimit(data.files, 1000, function (ref, next) {
+ fs.readFile(ref.srcPath, function (err, buffer) {
+ if (err) {
+ return next(err);
+ }
+
+ next(null, buffer.toString());
+ });
+ }, function (err, files) {
if (err) {
return callback(err);
}
var output = files.join('\n;');
- callback(null, { code: output });
+ fs.writeFile(data.destPath, output, callback);
});
return;
@@ -179,81 +185,108 @@ function concat(data, callback) {
}
actions.concat = concat;
-function minifyJS(data, callback) {
- if (data.batch) {
- async.eachLimit(data.files, 1000, function (ref, next) {
- var srcPath = ref.srcPath;
- var destPath = ref.destPath;
-
- fs.readFile(srcPath, function (err, buffer) {
- if (err && err.code === 'ENOENT') {
- return next(null, null);
- }
- if (err) {
- return next(err);
- }
-
- try {
- var minified = uglifyjs.minify(buffer.toString(), {
- // outSourceMap: data.filename + '.map',
- compress: data.compress,
- fromString: true,
- output: {
- // suppress uglify line length warnings
- max_line_len: 400000,
- },
- });
-
- fs.writeFile(destPath, minified.code, next);
- } catch (e) {
- next(e);
- }
- });
- }, callback);
-
- return;
- }
+function minifyJS_batch(data, callback) {
+ async.eachLimit(data.files, 1000, function (ref, next) {
+ var srcPath = ref.srcPath;
+ var destPath = ref.destPath;
+ var filename = ref.filename;
- if (data.files && data.files.length) {
- async.filter(data.files, file.exists, function (err, scripts) {
+ fs.readFile(srcPath, function (err, buffer) {
if (err) {
- return callback(err);
+ return next(err);
}
+ var scripts = {};
+ scripts[filename] = buffer.toString();
+
try {
var minified = uglifyjs.minify(scripts, {
- // outSourceMap: data.filename + '.map',
- compress: data.compress,
- fromString: false,
+ sourceMap: {
+ filename: filename,
+ url: filename + '.map',
+ includeSources: true,
+ },
});
- callback(null, minified);
+ async.parallel([
+ async.apply(fs.writeFile, destPath, minified.code),
+ async.apply(fs.writeFile, destPath + '.map', minified.map),
+ ], next);
} catch (e) {
- callback(e);
+ next(e);
}
});
+ }, callback);
+}
+actions.minifyJS_batch = minifyJS_batch;
- return;
- }
+function minifyJS(data, callback) {
+ async.mapLimit(data.files, 1000, function (ref, next) {
+ var srcPath = ref.srcPath;
+ var filename = ref.filename;
- callback();
+ fs.readFile(srcPath, function (err, buffer) {
+ if (err) {
+ return next(err);
+ }
+
+ next(null, {
+ srcPath: srcPath,
+ filename: filename,
+ source: buffer.toString(),
+ });
+ });
+ }, function (err, files) {
+ if (err) {
+ return callback(err);
+ }
+
+ var scripts = {};
+ files.forEach(function (ref) {
+ if (!ref) {
+ return;
+ }
+
+ scripts[ref.filename] = ref.source;
+ });
+
+ try {
+ var minified = uglifyjs.minify(scripts, {
+ sourceMap: {
+ filename: data.filename,
+ url: data.filename + '.map',
+ includeSources: true,
+ },
+ compress: {
+ hoist_funs: false,
+ },
+ });
+
+ async.parallel([
+ async.apply(fs.writeFile, data.destPath, minified.code),
+ async.apply(fs.writeFile, data.destPath + '.map', minified.map),
+ ], callback);
+ } catch (e) {
+ callback(e);
+ }
+ });
}
actions.minifyJS = minifyJS;
Minifier.js = {};
-Minifier.js.bundle = function (scripts, minify, fork, callback) {
+Minifier.js.bundle = function (data, minify, fork, callback) {
executeAction({
act: minify ? 'minifyJS' : 'concat',
- files: scripts,
- compress: false,
+ files: data.files,
+ filename: data.filename,
+ destPath: data.destPath,
}, fork, callback);
};
Minifier.js.minifyBatch = function (scripts, fork, callback) {
executeAction({
- act: 'minifyJS',
+ act: 'minifyJS_batch',
files: scripts,
- batch: true,
}, fork, callback);
};
diff --git a/test/build.js b/test/build.js
index 0d61283eac..b8c90f57e4 100644
--- a/test/build.js
+++ b/test/build.js
@@ -20,12 +20,28 @@ describe('minifier', function () {
var scripts = [
path.resolve(__dirname, './files/1.js'),
path.resolve(__dirname, './files/2.js'),
- ];
+ ].map(function (script) {
+ return {
+ srcPath: script,
+ destPath: path.resolve(__dirname, '../build/test', path.basename(script)),
+ filename: path.basename(script),
+ };
+ });
+
it('.js.bundle() should concat scripts', function (done) {
- minifier.js.bundle(scripts, false, false, function (err, bundle) {
+ var destPath = path.resolve(__dirname, '../build/test/concatenated.js');
+
+ minifier.js.bundle({
+ files: scripts,
+ destPath: destPath,
+ filename: 'concatenated.js',
+ }, false, false, function (err) {
assert.ifError(err);
+
+ assert(file.existsSync(destPath));
+
assert.strictEqual(
- bundle.code,
+ fs.readFileSync(destPath).toString(),
'(function (window, document) {' +
'\n\twindow.doStuff = function () {' +
'\n\t\tdocument.body.innerHTML = \'Stuff has been done\';' +
@@ -40,36 +56,40 @@ describe('minifier', function () {
done();
});
});
-
it('.js.bundle() should minify scripts', function (done) {
- minifier.js.bundle(scripts, true, false, function (err, bundle) {
+ var destPath = path.resolve(__dirname, '../build/test/minified.js');
+
+ minifier.js.bundle({
+ files: scripts,
+ destPath: destPath,
+ filename: 'minified.js',
+ }, true, false, function (err) {
assert.ifError(err);
+
+ assert(file.existsSync(destPath));
+
assert.strictEqual(
- bundle.code,
- '(function(n,o){n.doStuff=function(){o.body.innerHTML="Stuff has been done"}})(window,document);function foo(n,o){return\'The person known as "\'+n+\'" is \'+o+" years old"}'
+ fs.readFileSync(destPath).toString(),
+ '!function(n,o){n.doStuff=function(){o.body.innerHTML="Stuff has been done"}}(window,document);function foo(n,o){return\'The person known as "\'+n+\'" is \'+o+" years old"}' +
+ '\n//# sourceMappingURL=minified.js.map'
);
done();
});
});
it('.js.minifyBatch() should minify each script', function (done) {
- var s = scripts.map(function (script) {
- return {
- srcPath: script,
- destPath: path.resolve(__dirname, '../build/test', path.basename(script)),
- };
- });
- minifier.js.minifyBatch(s, false, function (err) {
+ minifier.js.minifyBatch(scripts, false, function (err) {
assert.ifError(err);
- assert(file.existsSync(s[0].destPath));
- assert(file.existsSync(s[1].destPath));
+ assert(file.existsSync(scripts[0].destPath));
+ assert(file.existsSync(scripts[1].destPath));
- fs.readFile(s[0].destPath, function (err, buffer) {
+ fs.readFile(scripts[0].destPath, function (err, buffer) {
assert.ifError(err);
assert.strictEqual(
buffer.toString(),
- '(function(n,o){n.doStuff=function(){o.body.innerHTML="Stuff has been done"}})(window,document);'
+ '!function(n,o){n.doStuff=function(){o.body.innerHTML="Stuff has been done"}}(window,document);' +
+ '\n//# sourceMappingURL=1.js.map'
);
done();
});