I migrated gulp from 3.9.1 to Gulp 4.0.2. Converted all the task as per Gulp 4 guidelines, however when I run 'gulp' from command line, all the tasks until 'nodemon
'
starts and finishes, but when it is about to start 'nodemon
',
it tries to start and then again continue loading the processing again and again. Might have missed some config, due to which it is causing issue.
Sharing new (v4.0.2) Gulpfile for reference along with GulpVariables, along with start console log.
New File
var gulp = require('gulp'); // Include gulp
var runsequence = require('run-sequence'); // used to run the different gulp task in a sequence
var deleteFiles = require('del'); // used to delete the files in dist folder for every build
var inject = require('gulp-inject'); // used to inject js and css files to index.html
var nodemon = require('gulp-nodemon'); // used to start the node server and watch for changes
var sourcemaps = require('gulp-sourcemaps'); // used to hold information about original files after minify
var concat = require('gulp-concat'); // used to append a file
var uglify = require('gulp-uglify'); // used to minify the js file
var cleancss = require('gulp-clean-css'); // used to clean up the css file
var obfuscate = require('gulp-js-obfuscator'); // used to obfuscate js file
//var git = require('gulp-git'); // used to work with git repo from gulp
var replacePaths = require('gulp-replace-path'); // used to change the src path for cloned repo
var jshint = require('gulp-jshint'); // used to check js files for errors and warnings
var jshintReporter = require('gulp-jshint-html-reporter'); // reporter to view the errors and warnings
var babel = require('gulp-babel'); // used to convert ES6 to ES5 because ES6 is not supported by uglify
var minifyImages = require('gulp-imagemin'); // used to minify images
var minifyejs = require('gulp-minify-ejs'); // used to minify mail templates which is in .ejs format
var liveReload = require('gulp-livereload'); // used to auromatically reload the browser when we change code
var gulpIf = require('gulp-if'); // execute a function based on a condition
var cache = require('gulp-cached'); // used to perform task only on changed files while watching
var chug = require('gulp-chug'); // used to run external gulpfile in case of remote build
var merge = require('merge-stream'); // used to have multiple source in single task
var rename = require('gulp-rename'); // used to have multiple source in single task
var gulpVariables = require('./gulpVariables.json'); // external file that contains directory path and other variables for the build
// removes the old files from the directory so that we get a clean build each time
function clean() {
return deleteFiles([gulpVariables.dist, gulpVariables.clone, gulpVariables.codeReviewReportName]); // delete the directory
};
//task to clone from remote repo
function cloneRepo() {
return git.clone(gulpVariables.remoteRepoUrl,{args: './'+gulpVariables.clone}, function (err) {
if (err) throw err;
process.chdir(gulpVariables.clone);
});
};
//task to checkout branch in local repo cloned from remote
function checkoutRepo() {
return git.checkout(gulpVariables.repoBranchName, function (err) {
if (err) throw err;
process.chdir('..');
});
};
function runGulpfileInsideClone() {
return gulp.src(gulpVariables.clone+'/gulpfile.js',{read:false})
.pipe(chug());
};
//review all js files for error
function staticCodeReview() {
return gulp.src([
gulpVariables.src + '/*.js',
gulpVariables.apiSrc + '/*.js',
gulpVariables.jsSrc + '/*.js',
gulpVariables.jsSrc + '/**/*.js',
gulpVariables.schedulerSrc + '/*.js'
])
.pipe(jshint())
.pipe(jshint.reporter(jshintReporter, {
filename: gulpVariables.codeReviewReportName
})
);
};
//copy src files without the nodeserver.js and folders to dist
function copySourceFoldersWithoutJSFiles() {
//Pass in all files in the root w/ no subdirectories to dist
//dot:true to make sure to copy .cfignore file
//.cfignore contains files to ignore to deploy in bluemix
var src = gulp.src([gulpVariables.src + '*','!'+gulpVariables.src +'*.js'], {dot: true});
var dest = gulp.dest(gulpVariables.dist);
return src.pipe(dest);
};
// copy vendor css files to dist
function copyVendorCSSFiles() {
return gulp.src(gulpVariables.vendorCSSSrc + '/**/*.css')
.pipe(concat(gulpVariables.combinedVendorCSSFileName))
.pipe(gulp.dest(gulpVariables.cssDest));
};
copyVendorCSSFiles.description = 'copy vendor css files to dist';
// optimise vendor css files in dist
async function optimiseVendorCSSFiles() {
if(gulpVariables.isOptimiseCSS) {
return gulp.src(gulpVariables.cssDest + '/' + gulpVariables.combinedVendorCSSFileName)
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.init()))
.pipe(cleancss())
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.write()))
.pipe(gulp.dest(gulpVariables.cssDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
}
};
optimiseVendorCSSFiles.description = 'optimise vendor css files in dist';
// copy vendor images to dist
function copyVendorImages() {
return gulp.src(gulpVariables.vendorImgSrc + '/**/*')
.pipe(gulp.dest(gulpVariables.imgDest));
};
// optimise vendor images in dist
async function optimiseVendorImages() {
if(gulpVariables.isOptimiseImages) {
return gulp.src(gulpVariables.vendorImgDest)
.pipe(minifyImages())
.pipe(gulp.dest(gulpVariables.vendorImgDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
}
};
// copy vendor js files to dist
function copyVendorJSFiles() {
var vendorJSWithoutPDFWorker = gulp.src([
gulpVariables.vendorJSSrc + '/**/angular.js', // this must be first
gulpVariables.vendorJSSrc + '/**/*.js', // all other files
'!' + gulpVariables.vendorJSSrc + '/**/pdf.worker.js'
])
.pipe(concat(gulpVariables.combinedVendorJSFileName))
.pipe(gulp.dest(gulpVariables.jsDest));
// ignoring the pdf.worker.js in the concatenated vendor file because for the PDF view it searches file with name pdf.worker.js
var PDFWorkerJS =gulp.src(gulpVariables.vendorJSSrc + '/vendor/pdf.worker.js')
.pipe(rename('vendor.min.worker.js'))
.pipe(gulp.dest(gulpVariables.jsDest));
return merge(vendorJSWithoutPDFWorker, PDFWorkerJS);
};
// optimise vendor js files in dist
async function optimiseVendorJSFiles() {
if(gulpVariables.isOptimiseJS) {
return gulp.src(gulpVariables.jsDest + '/' + gulpVariables.combinedVendorJSFileName)
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.init()))
.pipe(uglify())
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.write()))
.pipe(gulp.dest(gulpVariables.jsDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
}
};
// copy external css to dist
function copyCSSFiles() {
return gulp.src(gulpVariables.cssSrc + '/*.css')
.pipe(concat(gulpVariables.combinedAppCSSFileName))
.pipe(gulp.dest(gulpVariables.cssDest));
};
// optimise external css in dist
async function optimiseCSSFiles() {
if(gulpVariables.isOptimiseCSS){
return gulp.src(gulpVariables.cssDest + '/' + gulpVariables.combinedAppCSSFileName)
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.init()))
.pipe(cleancss())
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.write()))
.pipe(gulp.dest(gulpVariables.cssDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
}
};
// copy images to dist
function copyImages() {
return gulp.src(gulpVariables.imgSrc + '/*')
.pipe(gulp.dest(gulpVariables.imgDest));
};
// optimise images in dist
async function optimiseImages() {
if(gulpVariables.isOptimiseImages){
return gulp.src(gulpVariables.imgDest + '/*')
.pipe(minifyImages())
.pipe(gulp.dest(gulpVariables.imgDest))
.pipe(gulpIf(gulpVariables.env == 'dev', liveReload()));
}
};
// copy js files to dist
function copyJSFiles() {
return gulp.src([
gulpVariables.jsSrc + '/app.js', // this must be first
gulpVariables.jsSrc + '/**/*.js' // all other files
])
.pipe(concat(gulpVariables.combinedAppJSFileName))
.pipe(gulp.dest(gulpVariables.jsDest));
};
// optimise js files in dist
async function optimiseJSFiles() {
if(gulpVariables.isOptimiseJS) {
return gulp.src(gulpVariables.jsDest + '/' + gulpVariables.combinedAppJSFileName)
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.init()))
.pipe(babel({
presets: ['es2015']
}))
.pipe(uglify())
.pipe(obfuscate())
.pipe(gulpIf(gulpVariables.env == 'dev',sourcemaps.write()))
.pipe(gulp.dest(gulpVariables.jsDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
}
};
// copy nodeserver.js to dist
function copyNodeServerFile() {
return gulp.src(gulpVariables.src + '*.js')
.pipe(gulp.dest(gulpVariables.dist));
};
// optimise nodeserver.js in dist
async function optimiseNodeServerFile() {
if(gulpVariables.isOptimiseJS) {
return gulp.src(gulpVariables.dist + '/*.js')
.pipe(gulpIf(gulpVariables.env == 'prod',babel({
presets: ['es2015']
})))
.pipe(gulpIf(gulpVariables.env == 'prod',uglify()))
.pipe(gulpIf(gulpVariables.env == 'prod',obfuscate()))
.pipe(gulp.dest(gulpVariables.dist));
}
};
// copy api files to dist
function copyApiFiles() {
return gulp.src(gulpVariables.apiSrc + '/**/*.js')
.pipe(gulp.dest(gulpVariables.apiDest));
};
// optimise api files in dist
async function optimiseApiFiles() {
if(gulpVariables.isOptimiseJS) {
return gulp.src(gulpVariables.apiDest + '/**/*.js')
.pipe(cache())
.pipe(gulpIf(gulpVariables.env == 'prod',babel({
presets: ['es2015']
})))
.pipe(gulpIf(gulpVariables.env == 'prod', uglify()))
.pipe(gulpIf(gulpVariables.env == 'prod', obfuscate()))
.pipe(gulp.dest(gulpVariables.apiDest));
}
};
// copy mail templates to dist
function copyMailTemplates() {
return gulp.src(gulpVariables.mailTemplateSrc + '/**')
.pipe(gulp.dest(gulpVariables.mailTemplateDest));
};
// optimise mail templates in dist
async function optimiseMailTemplates() {
if(gulpVariables.isOptimiseJS) {
gulp.src(gulpVariables.mailTemplateDest + '/**')
.pipe(minifyejs())
.pipe(gulp.dest(gulpVariables.mailTemplateDest));
}
};
// copy scheduler to dist
function copySchedulerFiles() {
return gulp.src(gulpVariables.schedulerSrc + '/*.js')
.pipe(gulp.dest(gulpVariables.schedulerDest));
};
// optimise scheduler in dist
async function optimiseSchedulerFiles() {
if(gulpVariables.isOptimiseJS) {
return gulp.src(gulpVariables.schedulerDest + '/*.js')
.pipe(gulpIf(gulpVariables.env == 'prod', babel({
presets: ['es2015']
})))
.pipe(gulpIf(gulpVariables.env == 'prod', uglify()))
.pipe(gulpIf(gulpVariables.env == 'prod', obfuscate()))
.pipe(gulp.dest(gulpVariables.schedulerDest));
}
};
// group all vendor copy tasks
const copyAndOptimiseVendorCSSFiles = gulp.series(copyVendorCSSFiles, optimiseVendorCSSFiles);
const copyAndOptimiseVendorImages = gulp.series(copyVendorImages, optimiseVendorImages);
const copyAndOptimiseVendorJSFiles = gulp.series(copyVendorJSFiles, optimiseVendorJSFiles);
const copyAndOptimiseVendorFiles = gulp.series(gulp.parallel(copyAndOptimiseVendorCSSFiles, copyAndOptimiseVendorImages, copyAndOptimiseVendorJSFiles));
const copyAndOptimiseCSSFiles = gulp.series(copyCSSFiles, optimiseCSSFiles);
const copyAndOptimiseImages = gulp.series(copyImages, optimiseImages);
// copy html files to dist
function copyHtmlFiles() {
return gulp.src(gulpVariables.htmlSrc + '/**')
.pipe(cache())
.pipe(gulp.dest(gulpVariables.htmlDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
};
const copyAndOptimiseJSFiles = gulp.series(copyJSFiles, optimiseJSFiles);
// group all client side app files copy tasks
const copyAndOptimiseClientSideAppFiles = gulp.series(gulp.parallel(copyAndOptimiseCSSFiles, copyAndOptimiseImages, copyHtmlFiles, copyAndOptimiseJSFiles));
const copyAndOptimiseNodeServerFile = gulp.series(copyNodeServerFile, optimiseNodeServerFile);
const copyAndOptimiseApiFiles = gulp.series(copyApiFiles, optimiseApiFiles);
const copyAndOptimiseMailTemplates = gulp.series(copyMailTemplates, optimiseMailTemplates);
const copyAndOptimiseSchedulerFiles = gulp.series(copySchedulerFiles, optimiseSchedulerFiles);
// group all server side app files copy tasks
const copyAndOptimiseServerSideAppFiles = gulp.series(gulp.parallel(copyAndOptimiseNodeServerFile, copyAndOptimiseApiFiles, copyAndOptimiseMailTemplates, copyAndOptimiseSchedulerFiles));
function copyCertificates(){
return gulp.src(gulpVariables.certSrc + '/*.*')
.pipe(gulp.dest(gulpVariables.certDest));
};
// copy index html file to dist
function injectIndexFile() {
var jsSrc,cssSrc,injectSrc;
jsSrc = [
gulpVariables.jsDest + '/vendor.min.js',
gulpVariables.jsDest + '/vendor.min.worker.js',
gulpVariables.jsDest + '/' + gulpVariables.combinedAppJSFileName
];
cssSrc = [
gulpVariables.cssDest + '/' + gulpVariables.combinedVendorCSSFileName,
gulpVariables.cssDest + '/' + gulpVariables.combinedAppCSSFileName
];
injectSrc = jsSrc.concat(cssSrc);
gulp.src(gulpVariables.indexSrc + '/index.html')
.pipe(inject(gulp.src(injectSrc),
{ignorePath: 'dist/public', addRootSlash: false}
))
.pipe(gulp.dest(gulpVariables.indexDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
};
function injectIndexFileVanillaCopy() {
return gulp.src(gulpVariables.indexSrc + '/index.html')
.pipe(gulp.dest(gulpVariables.indexDest))
.pipe(gulpIf(gulpVariables.env == 'dev',liveReload()));
};
// nodemon to start the server
function nodemon() {
if(gulpVariables.env == 'dev') {
nodemon({
script: gulpVariables.dist + '/' + gulpVariables.nodeServerFileName,
ext: 'js',
delay: "10000",
watch:[gulpVariables.apiDest, gulpVariables.dist + gulpVariables.nodeServerFileName, gulpVariables.schedulerDest]
});
}
};
// Watch Files For Changes and calls the gulp task if any change happens
function watch() {
if(gulpVariables.env == 'dev') {
liveReload.listen();
watch([gulpVariables.src + '*','!'+gulpVariables.src +'*.js'], copySourceFoldersWithoutJSFiles);
watch(gulpVariables.src + '*.js', copyAndOptimiseNodeServerFile);
watch(gulpVariables.apiSrc + '/**/*.js', copyAndOptimiseApiFiles);
watch(gulpVariables.mailTemplateSrc + '/**', copyAndOptimiseMailTemplates);
watch(gulpVariables.schedulerSrc + '/*.js', copyAndOptimiseSchedulerFiles);
watch(gulpVariables.cssSrc + '/*.css', copyAndOptimiseCSSFiles);
watch(gulpVariables.imgSrc + '/*', copyAndOptimiseImages);
watch(gulpVariables.htmlSrc + '/**', copyHtmlFiles);
watch(gulpVariables.jsSrc + '/**', copyAndOptimiseJSFiles);
watch(gulpVariables.indexSrc + '/index.html', injectIndexFileVanillaCopy);
watch(gulpVariables.vendorCSSSrc + '/**', copyAndOptimiseVendorCSSFiles);
watch(gulpVariables.vendorImgSrc + '/**', copyAndOptimiseVendorImages);
watch(gulpVariables.vendorJSSrc + '/**', copyAndOptimiseVendorJSFiles);
}
};
/*
* Specify if tasks run in series or parallel using `gulp.series` and `gulp.parallel`
*/
var build = gulp.series(clean, copySourceFoldersWithoutJSFiles, copyAndOptimiseVendorFiles, copyAndOptimiseClientSideAppFiles, copyAndOptimiseServerSideAppFiles, copyCertificates, injectIndexFileVanillaCopy, nodemon);
//var build = gulp.series(server, watch);
/*
* You can use CommonJS `exports` module notation to declare tasks
*/
/*exports.clean = clean;
exports.cloneRepo = cloneRepo;
exports.staticCodeReview = staticCodeReview;
exports.checkoutRepo = checkoutRepo;
exports.copySourceFoldersWithoutJSFiles = copySourceFoldersWithoutJSFiles;
exports.copyVendorCSSFiles = copyVendorCSSFiles;
exports.optimiseVendorCSSFiles = optimiseVendorCSSFiles;
exports.copyAndOptimiseVendorCSSFiles = copyAndOptimiseVendorCSSFiles;
exports.copyVendorImages = copyVendorImages
exports.optimiseVendorImages = optimiseVendorImages;
exports.copyAndOptimiseVendorImages = copyAndOptimiseVendorImages;
exports.copyVendorJSFiles = copyVendorJSFiles;
exports.optimiseVendorJSFiles = optimiseVendorJSFiles;
exports.copyAndOptimiseVendorJSFiles = copyAndOptimiseVendorJSFiles;
exports.copyAndOptimiseVendorFiles = copyAndOptimiseVendorFiles;
exports.copyCSSFiles = copyCSSFiles;
exports.optimiseCSSFiles = optimiseCSSFiles;
exports.copyAndOptimiseCSSFiles = copyAndOptimiseCSSFiles;
exports.copyImages = copyImages;
exports.optimiseImages = optimiseImages;
exports.copyAndOptimiseImages = copyAndOptimiseImages
exports.copyHtmlFiles = copyHtmlFiles;
exports.copyJSFiles = copyJSFiles;
exports.optimiseJSFiles = optimiseJSFiles;
exports.copyAndOptimiseJSFiles = copyAndOptimiseJSFiles;
exports.copyAndOptimiseClientSideAppFiles = copyAndOptimiseClientSideAppFiles;
exports.copyNodeServerFile = copyNodeServerFile;
exports.optimiseNodeServerFile = optimiseNodeServerFile;
exports.copyAndOptimiseNodeServerFile = copyAndOptimiseNodeServerFile;
exports.copyApiFiles = copyApiFiles;
exports.optimiseApiFiles = optimiseApiFiles;
exports.copyAndOptimiseApiFiles = copyAndOptimiseApiFiles;
exports.copyMailTemplates = copyMailTemplates;
exports.optimiseMailTemplates = optimiseMailTemplates;
exports.copyAndOptimiseMailTemplates = copyAndOptimiseMailTemplates;
exports.copySchedulerFiles = copySchedulerFiles;
exports.optimiseSchedulerFiles = optimiseSchedulerFiles;
exports.copyAndOptimiseSchedulerFiles = copyAndOptimiseSchedulerFiles;
exports.copyAndOptimiseServerSideAppFiles = copyAndOptimiseServerSideAppFiles;
exports.copyCertificates = copyCertificates;
exports.injectIndexFileVanillaCopy = injectIndexFileVanillaCopy;
exports.nodemon = nodemon;
exports.watch = watch;*/
/*
* Define default task that can be called by just running `gulp` from cli
*/
exports.default = build;
Gulp Variables File
{
"src": "src/",
"dist": "dist",
"apiSrc": "src/api",
"apiDest": "dist/api",
"certSrc": "src/certificate",
"certDest": "dist/certificate",
"mailTemplateSrc": "src/mailTemplates",
"mailTemplateDest": "dist/mailTemplates",
"schedulerSrc": "src/scheduler",
"schedulerDest": "dist/scheduler",
"cssSrc": "src/public/css",
"cssDest": "dist/public/css",
"imgSrc": "src/public/images",
"imgDest": "dist/public/images",
"vendorImgDest": "dist/public/images/vendor",
"htmlSrc": "src/public/html",
"htmlDest": "dist/public/html",
"jsSrc": "src/public/js",
"jsDest": "dist/public/js",
"vendorCSSSrc": "vendor/css",
"vendorImgSrc": "vendor/images",
"vendorJSSrc": "vendor/js",
"indexSrc": "src/public",
"indexDest": "dist/public",
"isRemoteBuild" : false,
"clone": "clone",
"remoteRepoUrl" : "",
"repoBranchName" : "dev",
"codeReviewReportName" : "codeReviewReport.html",
"env": "dev",
"combinedAppJSFileName":"app.min.js",
"combinedVendorJSFileName":"vendor.min.js",
"combinedAppCSSFileName":"app.min.css",
"combinedVendorCSSFileName":"vendor.min.css",
"combinedApiFileName":"api.min.js",
"nodeServerFileName":"nodeServer.js",
"isOptimiseCSS": false,
"isOptimiseJS":false,
"isOptimiseImages":false
}
When I run gulp
on command line, it all works fine (appears to be) till function/task - injectIndexFileVanillaCopy
. Moment I add nodemon
function/task, it tries to start the process and then again restarts it again and again as seen in below image/console output
Converted gulpfile from v 3.9.1 to v4.0.2, using series & parallel api with on change in execution order. Expecting to run/start the process cleanly, but server/node/process going in loop. Might be some config issue with watch
and nodemon
, unable to figure that out. Have gone thru multiple links, but not able to root cause
I have spent nearly 4-5 days screening through multiple topics, links for Gulp 3 --> Gulp 4 migration, but couldn't find any good/working solution that is fully utilizing Gulp 4 capabilities like, creating/exporting
task
, creating/usingfunctions
, usingseries/parallel
,watch
,run-sequence
andnodemon
features and lastly functioncallbacks
.Eventually after multiple trial and error, I got the gulp 3.9.1
gulpfile
to gulp 4.0.2 version.Sharing few things below from my learning, may be some of these are already in public domain.
Callback
- If function isreturn
ing, then no need to explicitly usedone()
task
and hence need to beexported
(registered)run-sequence
npm
module, convert it toseries
gulp
3.xtask
created as below, possible suggestion is to convert it toparallel
OLD
NEW
watch
items define as below, then again a suggestion is to convert it like the one given as NEW approach.OLD
NEW
While you upgrade gulp 3.x to 4.x, you might have few other node module, that are old, old as per current version of respective module. Please don't upgrade them to current version blindly. Run
npm outdated
command to get the snapshot of what is outdated and needs to be updated.Updated only those outdated
npm
modules to 'Wanted' version instead of 'Latest' one.Few keywords like
watch
,nodemon
, are actually keywords and might create a problem in gulp 4.x. What I mean here is, you gulp 3.x will work with below function definitiongulp.task('nodemon', function() {....})
gulp.task('watch', function() {....})
but it might create problem in gulp 4.x. Please use different names for functions or task, as you would see in working version below.
I definitely found few URLs (
stackoverflow
,youtube
) useful in order to build understanding about this migration and get it to work state. Can shore those if someone is really interested and curious.Lastly sharing the working version, which I was hoping for when I posted this question.
Working
gulpfile