Skip to content

Instantly share code, notes, and snippets.

@jbalducc
Last active December 11, 2015 10:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbalducc/4589709 to your computer and use it in GitHub Desktop.
Save jbalducc/4589709 to your computer and use it in GitHub Desktop.
A grunt file to be added in yeoman build task after rjs and rev tasks. input : /<md5>.main.js /<md5>.core.js /package/<md5>.pack1.js output : /<md5>.main.js /<md5>.main.src.js /<md5>.main.js.map /<md5>.core.js /<md5>.core.src.js /<md5>.core.js.map /<md5>.pack1.js /<md5>.pack1.src.js /<md5>.pack1.js.map with main.js containing a map in paths with…
grunt.registerTask('finalize', function () {
var cdnBaseUrl = "//mycdn/scripts/"; // CDN Url where files will be hosted
var pathBase = "./dist/scripts/"; // Local directory where files are already optimized with rjs and already revved (like d4edefds.file.js)
function revmd5(fileContent) {
var hash = crypto.createHash("md5");
hash.update(fileContent);
// 8 chars will be sufficient
return hash.digest('hex').slice(0, 8);
}
var _und = require("./app/scripts/vendor/lodash/0.9.2/lodash");
// Use the same config as the rjs task
var options = grunt.config("rjs") || {};
// assume that main.js is always present in pathBase (not a subdirectory)
// find the name revved
var mainjsBaseName = _und.find(fs.readdirSync(pathBase), function (file) {
var last = new RegExp("main.js$");
return last.test(file)
});
// load text content of main.js (replace are here just to ease some replace)
var mainjsContent = (fs.readFileSync(path.resolve(pathBase, mainjsBaseName)) + '')
.replace(/\n/g, '')
.replace(/ /g, "");
// Retrieve all the layers built from rjs config
var layers = [];
_und.each(options.modules, function (elt) {
layers.push(elt.name)
});
// paths will store all the mapping "moduleId": "file"
var paths = "";
// cdnUrl will store all the network path to access built files
// It's javascript text. Will be added to mainjs
// Just to avoid writing the complete url in paths many times
var cdnUrl = 'var cdnUrl="' + cdnBaseUrl + '/";';
var defineRegEx = /define\(("([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'),/g;
_und.each(layers, function (layer) {
layer = layer + ".js";
var origBasename = path.basename(layer);
var origDirname = path.dirname(layer);
var ls = fs.readdirSync(pathBase + origDirname);
// find the name revved of the built file
var revvedBasename = _und.find(ls, function (file) {
var last = new RegExp(origBasename + "$");
return last.test(file)
});
console.log(revvedBasename);
// Add this file to cdnUrl
cdnUrl += 'var ' + origBasename.replace('.js', '') + 'Url' + '=cdnUrl+"' + revvedBasename.replace('.js', '') + '";';
// Read the content of the built layer as text
var origContent = fs.readFileSync(path.resolve(pathBase + origDirname, revvedBasename)) + '';
// Find all the moduleIds in the built layer
var matches = origContent.match(defineRegEx);
for (var j = 0; j < matches.length; j++) {
matches[j] = matches[j].substr(8, matches[j].length - 10);
}
// For each moduleIds add a mapping in paths
_und.each(matches, function (elt) {
// Don't map i18n ids
if (elt.indexOf('_i18n_') != 0) {
paths += '"' + elt + '"' + ":" + origBasename.replace('.js', '') + ',';
}
});
// move to pathBase and with .src.js extension
fs.renameSync(path.resolve(pathBase + origDirname, revvedBasename), path.resolve(pathBase, revvedBasename.replace('.js', '') + '.src.js'));
// minify built layer with uglify
var uglify = UglifyJS.minify(origContent, {
outSourceMap: revvedBasename,
fromString: true,
sourceRoot: 'http:' + cdnBaseUrl
});
uglify.code = "//@ sourceMappingURL=http:" + cdnBaseUrl + revvedBasename + ".map\n" + uglify.code;
uglify.map = uglify.map.replace('"sources":["?"]', '"sources":["' + revvedBasename.replace('.js', '') + '.src.js' + '"]');
// Write the minified file
fs.writeFileSync(path.resolve(pathBase, revvedBasename), uglify.code);
// Write the source map file
fs.writeFileSync(path.resolve(pathBase, revvedBasename + '.map'), uglify.map);
});
// Add cdnUrl just after (function() {
mainjsContent = mainjsContent.replace('(function() {', '(function() {\n' + cdnUrl);
// Replace initial content beetween /*START_PATH*/ end /*END_PATH*/ with the calculated map
mainjsContent = mainjsContent.replace(/\/\*START_PATH\*\/.*\/\*END_PATH\*\//, paths.replace(/,$/, ''));
// Uglify content
var uglify = UglifyJS.minify(mainjsContent, {
outSourceMap: mainjsBaseName,
fromString: true,
sourceRoot: 'http:' + cdnBaseUrl
});
uglify.code = "//@ sourceMappingURL=http:" + cdnBaseUrl + mainjsBaseName + ".map\n" + uglify.code;
uglify.map = uglify.map.replace('"sources":["?"]', '"sources":["' + mainjsBaseName.replace('.js', '') + '.src.js' + '"]');
// Rename file to .src.js
fs.renameSync(path.resolve(pathBase, mainjsBaseName), path.resolve(pathBase, mainjsBaseName.replace('.js', '') + '.src.js'));
// Write the minified file
fs.writeFileSync(path.resolve(pathBase, mainjsBaseName), uglify.code);
// Write the source map file
fs.writeFileSync(path.resolve(pathBase, mainjsBaseName + '.map'), uglify.map);
console.log(mainjsBaseName);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment