shunter
Version:
A Node.js application built to read JSON and translate it into HTML
176 lines (156 loc) • 4.46 kB
JavaScript
;
var yargs = require('yargs');
var argv = yargs
.options('x', {
alias: 'extra-js',
type: 'string'
})
.options('r', {
alias: 'resource-module',
type: 'string'
})
.alias('h', 'help')
.help()
.describe({
x: 'Extra JS paths to minify',
r: 'Name of modules with resources to include in the build, can specify several of these flags'
})
.argv;
var config = require('../lib/config')('production', null, {});
var async = require('async');
var fs = require('fs');
var path = require('path');
var glob = require('glob');
var mkdirp = require('mkdirp');
var uglify = require('uglify-js');
// All files named main.js will be minfied, extra files to minify can be specified here
var EXTRA_MINIFY_PATHS = [];
if (argv['extra-js']) {
EXTRA_MINIFY_PATHS = Array.isArray(argv['extra-js']) ? argv['extra-js'] : [argv['extra-js']];
}
var resourceModules;
if (argv['resource-module']) {
resourceModules = (
Array.isArray(argv['resource-module']) ?
argv['resource-module'] :
[argv['resource-module']]
);
config.modules = resourceModules;
}
var renderer = require('../lib/renderer')(config);
var environment = renderer.environment;
var manifest = renderer.manifest;
environment.cssCompressor = 'csswring';
// crude listener for errors, replace with domain once that is stable
process.on('uncaughtException', function(err) {
console.error('Caught exception: ' + err);
process.exit(128);
});
var compile = function(data, callback) {
var findAssets = function() {
var pattern = new RegExp('\.(' + [].slice.call(arguments, 0).join('|') + ')$');
return Object.keys(data.assets).filter(function(key) {
return key.match(pattern);
});
};
var deleteAsset = function(name) {
delete manifest.assets[name];
return null;
};
var stylesheets = findAssets('css').map(function(name) {
var asset = environment.findAsset(name);
var content = asset ? asset.toString() : null;
if (!content) {
return deleteAsset(name);
}
return {
path: config.path.publicResources + '/' + data.assets[name],
content: content
};
}).filter(function(stylesheet) {
return stylesheet !== null;
});
var jsToMinify = ['main'].concat(EXTRA_MINIFY_PATHS);
var javascripts = findAssets('js').filter(function(name) {
for (var i = 0; jsToMinify[i]; ++i) {
if (name.indexOf(jsToMinify[i]) !== -1) {
return true;
}
}
return false;
}).map(function(name) {
var asset = environment.findAsset(name);
var content = asset ? asset.toString() : null;
var start;
var end;
if (!content) {
return deleteAsset(name);
}
start = new Date();
content = uglify.minify(content, {
fromString: true
}).code;
end = new Date();
// Note: suspect this part of the process is timing out on build, extra logging to test
console.log('Uglifying ' + name + ' took ' + (end - start) + 'ms');
return {
path: config.path.publicResources + '/' + data.assets[name],
content: content
};
}).filter(function(script) {
return script !== null;
});
// Save the updated stylesheets and javascripts, then save the manifest
async.map(stylesheets.concat(javascripts), function(resource, fn) {
console.log('Writing resource to ' + resource.path);
fs.writeFile(resource.path, resource.content, 'utf8', fn);
}, function() {
manifest.save(callback);
});
};
var generate = function(callback) {
async.waterfall([
function(fn) {
mkdirp(config.path.publicResources, fn);
},
function(dir, fn) {
// glob returns absolute path and we need to strip that out
var readGlobDir = function(p, cb) {
var pth = p.replace(/\\\?/g, '\/'); // glob must use / as path seperator even on windows
glob(pth + '/**/*.*', function(er, files) {
if (er) {
return cb(er);
}
return cb(null, files.map(function(f) {
return path.relative(p, f);
}));
});
};
// returns a flat array of files with relative paths
async.concat(environment.paths, readGlobDir, fn);
},
function(files) {
var data = null;
try {
data = manifest.compile(files.map(function(file) {
return file.replace(/\.ejs$/, '');
}));
} catch (e) {
callback(e, null);
}
if (data) {
compile(data, callback);
}
}
]);
};
generate(function(err) {
if (err) {
console.error('Failed to generate manifest: ' + (err.message || err.toString()));
process.exit(128);
} else {
console.log('Manifest compiled');
process.exit(0);
}
});