Skip to content

Instantly share code, notes, and snippets.

@CodeXT1
Last active May 24, 2016 08:44
Show Gist options
  • Save CodeXT1/890d0e990d5e2bd1e8fe to your computer and use it in GitHub Desktop.
Save CodeXT1/890d0e990d5e2bd1e8fe to your computer and use it in GitHub Desktop.
RequireJS, r.js multi-bundle edge case with Gulp-Rev-All. RequireJS doesn't like to have .js extentions on bundles, even though they often map directly to .js files, so Gulp-Rev-All misses them. This is a very hack script I made to run after Gulp-Rev-All has hashed everything else. It loads *.js files in the final build directory and parses out …
var gulp = require('gulp'),
glob = require('glob'),
$ = require('gulp-load-plugins');
//Needs gulp-replace too, you'll see
//and gulp-rev-all is assumed to have already been run on the whole build dir.
// This is the gulp task to replace the few missed link references in the RequireJS
// common bundle after using the Gulp-Rev-All to hash and update everything else
gulp.task('bundle-replace', function() {
// Select the RequireJS main scripts*.js bundle as it will be our final output
// and it is a good start for of the gulp pipe. It has gone through
// "r.js optimzer" and Gulp-Rev-All already, hence the *.js to grab it with the
// hash
return gulp.src(['./build/scripts*.js'])
// Use Gulp-replace aliased to $.replace. We are using RegEx to target the lazy
// loaded bundles inside the scripts*.js, they will have patterns like
// "about":[ or "chart":[ or "options-page":[ etc, that map to real .js files
// if they had .js extensions added to them. The variable "p1" holds onto the
// Regex Capture Group () that found the base filenames of the bundles we want
// to change and we will match against it later.
// (RequireJS doesn't like .js extensions on the bundles, but I tested it
// anyway and if they could have .js added then Rev-All finds them,
// so great work, had they been normal file links this wouldn't be an issue
// but RequireJS wants to not have .js added on the end)
// http://imgur.com/n5dbBTO.png This is an image example of the bundles that need to
// be hashed, and these are what this first RegEx finds for us in our common bundle
.pipe($.replace(/\"([^"]*)\"\:\s?\[\s*\"/g, function(match, p1) {
// Glob assign all *.js files in Build Dir that have already be rev'd with Rev-All
var allRevFiles = glob.sync('./build/*.js');
// Turn the JSON glob into a jsonString
var jsonString = JSON.stringify(allRevFiles);
// this RegEx has two Capture groups with () inside () if you notice:
// one with the full file name and hash, without the .js, what we want it to turn into
// and one with just the file name, no hash and no .js, what it currently is, and what
// is currently being stored in the "p1" variable to be matched against later
var regEx = /\"\.\/[a-z]*\/(([^\"\/.]*).[a-z0-9.]*)\.js\"/ig
// Define a single plainFile to loop with, and a allPlainFiles array to push results into
var plainFile;
var allPlainFiles = [];
// loop through the matching RegEx compared to all our hashed *.js files in Build Dir
// to build our array
while (plainFile = regEx.exec(jsonString)){
// Push Capture group 1 and 2 into the array
allPlainFiles.push(plainFile[2]);
allPlainFiles.push(plainFile[1]);
};
// simple loop over the size of the allPlainFiles Array
for (var i = 0; i < allPlainFiles.length; i++) {
// if the Capture group 2 matches the "p1" found in the file, replace it with Capture
// group 1's related full filename, the one with the hash added so +1 in
// the Array compared to the one the matched so we replace it with what we want.
if (allPlainFiles[i] === p1) {
// return it with extra formatting because the first RegEx we did removes some extra
// characters with its matching due to having to match against extra symbols like ":[
// in order to make sure the bundle names it found were unique in the fully concatenated
// common bundle scripts*.js file, because there are other libraries in there too now.
// So Add back in a starting " and a closing ":[
return "\""+ allPlainFiles[i+1] +"\"\:\[\"";
}
};
}))
// This is final pipe writes the changes to Scripts*.js with gulp-replace to change the
// desired bundle names to the hashed versions. It all takes about 40ms to finish, great hack.
.pipe(gulp.dest('./build'));
});
// This image is how it should look after being replaced, and works it works now that the
// Bundle Names are hashed! http://imgur.com/xlPGbBT.png
// The RegEx is used was built and tested with http://www.regexr.com/, great site.
// This is a small example of a jsonString from the Gist that would represent the .js files
// in your build dir after using Rev-All, and you'd match it with
//from line 42
// /\"\.\/[a-z]*\/(([^\"\/.]*).[a-z0-9.]*)\.js\"/ig
// ["./build/about.4633414d.js","./build/back-end.4633414d.js","./build/charts.fb997bcb.js",
// "./build/etc.fb997bcb.js","./build/scripts.ee82b2ec.js"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment