Improved asset manifest file change handling in Gulpfile.js.

Code now only restarts watchers for the asset groups in the changed asset manifest file, rather than *all* asset groups. The "build" task now forces rebuild of a given asset group if its asset manifest file is newer than its concatenated output. Refactored and cleaned up the code.
This commit is contained in:
Daniel Stolt
2015-09-16 16:56:51 +02:00
parent 40071a6050
commit b011594be6
6 changed files with 38 additions and 43 deletions

View File

@@ -1,4 +1,5 @@
var glob = require("glob"), var fs = require("fs"),
glob = require("glob"),
path = require("path-posix"), path = require("path-posix"),
merge = require("merge-stream"), merge = require("merge-stream"),
gulpif = require("gulp-if"), gulpif = require("gulp-if"),
@@ -13,8 +14,7 @@ var glob = require("glob"),
uglify = require("gulp-uglify"), uglify = require("gulp-uglify"),
rename = require("gulp-rename"), rename = require("gulp-rename"),
concat = require("gulp-concat"), concat = require("gulp-concat"),
header = require("gulp-header"), header = require("gulp-header");
fs = require("fs");
/* /*
** GULP TASKS ** GULP TASKS
@@ -38,22 +38,14 @@ gulp.task("rebuild", function () {
return merge(assetGroupTasks); return merge(assetGroupTasks);
}); });
// Continuous watch (each asset group is built whenever one of its inputs changes).
// Set "Watchers" as sub-processes in order to restart the task when Assets.json changes.
gulp.task("watch", function () { gulp.task("watch", function () {
var watchers; var pathWin32 = require("path");
function restart() { getAssetGroups().forEach(function (assetGroup) {
if (watchers) { var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths);
watchers.forEach(function (w) { var inputWatcher;
w.remove(); function createWatcher() {
w.end(); inputWatcher = gulp.watch(watchPaths, function (event) {
});
}
watchers = [];
// Continuous watch (each asset group is built whenever one of its inputs changes).
getAssetGroups().forEach(function (assetGroup) {
var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths);
var watcher = gulp.watch(watchPaths, function (event) {
var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@"; var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@";
if (isConcat) if (isConcat)
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'."); console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'.");
@@ -62,29 +54,26 @@ gulp.task("watch", function () {
var doRebuild = true; var doRebuild = true;
var task = createAssetGroupTask(assetGroup, doRebuild); var task = createAssetGroupTask(assetGroup, doRebuild);
}); });
watchers.push(watcher); }
createWatcher();
gulp.watch(assetGroup.manifestPath, function (event) {
console.log("Asset manifest file '" + event.path + "' was " + event.type + ", restarting watcher.");
inputWatcher.remove();
inputWatcher.end();
createWatcher();
}); });
}
var p;
if (p) { p.exit(); }
p = gulp.watch("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", function (event) {
console.log("Asset file '" + event.path + "' was " + event.type + ", resetting asset watchers.");
restart();
}); });
restart();
}); });
/* /*
** ASSET GROUPS ** ASSET GROUPS
*/ */
function getAssetGroups() { function getAssetGroups() {
var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", {}); var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json");
var assetGroups = []; var assetGroups = [];
assetManifestPaths.forEach(function (assetManifestPath) { assetManifestPaths.forEach(function (assetManifestPath) {
var file = './' + assetManifestPath; var assetManifest = require("./" + assetManifestPath);
var json = fs.readFileSync(file, 'utf8');
assetManifest = eval(json);
assetManifest.forEach(function (assetGroup) { assetManifest.forEach(function (assetGroup) {
resolveAssetGroupPaths(assetGroup, assetManifestPath); resolveAssetGroupPaths(assetGroup, assetManifestPath);
assetGroups.push(assetGroup); assetGroups.push(assetGroup);
@@ -94,6 +83,7 @@ function getAssetGroups() {
} }
function resolveAssetGroupPaths(assetGroup, assetManifestPath) { function resolveAssetGroupPaths(assetGroup, assetManifestPath) {
assetGroup.manifestPath = assetManifestPath;
assetGroup.basePath = path.dirname(assetManifestPath); assetGroup.basePath = path.dirname(assetManifestPath);
assetGroup.inputPaths = assetGroup.inputs.map(function (inputPath) { assetGroup.inputPaths = assetGroup.inputs.map(function (inputPath) {
return path.resolve(path.join(assetGroup.basePath, inputPath)); return path.resolve(path.join(assetGroup.basePath, inputPath));
@@ -111,11 +101,18 @@ function resolveAssetGroupPaths(assetGroup, assetManifestPath) {
function createAssetGroupTask(assetGroup, doRebuild) { function createAssetGroupTask(assetGroup, doRebuild) {
var outputExt = path.extname(assetGroup.output).toLowerCase(); var outputExt = path.extname(assetGroup.output).toLowerCase();
var doConcat = path.basename(assetGroup.outputFileName, outputExt) !== "@";
if (doConcat && !doRebuild) {
// Force a rebuild of this asset group is the asset manifest file itself is newer than the output.
var assetManifestStats = fs.statSync(assetGroup.manifestPath);
var outputStats = fs.statSync(assetGroup.outputPath);
doRebuild = !outputStats || assetManifestStats.mtime > outputStats.mtime;
}
switch (outputExt) { switch (outputExt) {
case ".css": case ".css":
return buildCssPipeline(assetGroup, doRebuild); return buildCssPipeline(assetGroup, doConcat, doRebuild);
case ".js": case ".js":
return buildJsPipeline(assetGroup, doRebuild); return buildJsPipeline(assetGroup, doConcat, doRebuild);
} }
} }
@@ -123,13 +120,12 @@ function createAssetGroupTask(assetGroup, doRebuild) {
** PROCESSING PIPELINES ** PROCESSING PIPELINES
*/ */
function buildCssPipeline(assetGroup, doRebuild) { function buildCssPipeline(assetGroup, doConcat, doRebuild) {
assetGroup.inputPaths.forEach(function (inputPath) { assetGroup.inputPaths.forEach(function (inputPath) {
var ext = path.extname(inputPath).toLowerCase(); var ext = path.extname(inputPath).toLowerCase();
if (ext !== ".less" && ext !== ".css") if (ext !== ".less" && ext !== ".css")
throw "Input file '" + inputPath + "' is not of a valid type for output file '" + assetGroup.outputPath + "'."; throw "Input file '" + inputPath + "' is not of a valid type for output file '" + assetGroup.outputPath + "'.";
}); });
var doConcat = path.basename(assetGroup.outputFileName, ".css") !== "@";
var generateSourceMaps = assetGroup.hasOwnProperty("generateSourceMaps") ? assetGroup.generateSourceMaps : true; var generateSourceMaps = assetGroup.hasOwnProperty("generateSourceMaps") ? assetGroup.generateSourceMaps : true;
return gulp.src(assetGroup.inputPaths) return gulp.src(assetGroup.inputPaths)
.pipe(gulpif(!doRebuild, .pipe(gulpif(!doRebuild,
@@ -160,13 +156,12 @@ function buildCssPipeline(assetGroup, doRebuild) {
.pipe(gulp.dest(assetGroup.outputDir)); .pipe(gulp.dest(assetGroup.outputDir));
} }
function buildJsPipeline(assetGroup, doRebuild) { function buildJsPipeline(assetGroup, doConcat, doRebuild) {
assetGroup.inputPaths.forEach(function (inputPath) { assetGroup.inputPaths.forEach(function (inputPath) {
var ext = path.extname(inputPath).toLowerCase(); var ext = path.extname(inputPath).toLowerCase();
if (ext !== ".ts" && ext !== ".js") if (ext !== ".ts" && ext !== ".js")
throw "Input file '" + inputPath + "' is not of a valid type for output file '" + assetGroup.outputPath + "'."; throw "Input file '" + inputPath + "' is not of a valid type for output file '" + assetGroup.outputPath + "'.";
}); });
var doConcat = path.basename(assetGroup.outputFileName, ".js") !== "@";
var generateSourceMaps = assetGroup.hasOwnProperty("generateSourceMaps") ? assetGroup.generateSourceMaps : true; var generateSourceMaps = assetGroup.hasOwnProperty("generateSourceMaps") ? assetGroup.generateSourceMaps : true;
return gulp.src(assetGroup.inputPaths) return gulp.src(assetGroup.inputPaths)
.pipe(gulpif(!doRebuild, .pipe(gulpif(!doRebuild,

View File

@@ -6,4 +6,4 @@
display: none; display: none;
} }
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
{ {
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"fs": "^0.0.2",
"glob": "^5.0.14", "glob": "^5.0.14",
"path-posix": "^1.0.0", "path-posix": "^1.0.0",
"merge-stream": "^0.1.8", "merge-stream": "^0.1.8",
@@ -16,8 +17,7 @@
"gulp-uglify": "^1.2.0", "gulp-uglify": "^1.2.0",
"gulp-rename": "^1.2.2", "gulp-rename": "^1.2.2",
"gulp-concat": "^2.5.2", "gulp-concat": "^2.5.2",
"gulp-header": "^1.2.2", "gulp-header": "^1.2.2"
"fs": "^0.0.2"
}, },
"dependencies": { } "dependencies": { }
} }