Last active
December 11, 2015 10:49
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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