Gulp default task unable to compress after copy - gulp

At first I thought this was related to dependency of tasks so I went with run-sequence and even tried defining dependencies within tasks themselves. But I cannot get the compress task to run after copy. Or, even if it says it did finish the compress task, the compression only works if I run compress in the task runner inside visual studio by itself. What else can I try to get it to compress after copy?
/// <binding BeforeBuild='default' />
/*
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. https://go.microsoft.com/fwlink/?LinkId=518007
*/
var gulp = require("gulp");
var debug = require("gulp-debug");
var del = require("del");
var uglify = require("gulp-uglify");
var pump = require("pump");
var runSequence = require("run-sequence");
var paths = {
bower: "./bower_components/",
lib: "./Lib/"
};
var modules = {
"store-js": ["store-js/dist/store.legacy.js"],
"bootstrap-select": [
"bootstrap-select/dist/css/bootstrap-select.css",
"bootstrap-select/dist/js/bootstrap-select.js",
"bootstrap-select/dist/js/i18n/*.min.js"
]
}
gulp.task("default", function (cb) {
runSequence("clean", ["copy", "compress"], cb);
});
gulp.task("clean",
function () {
return del.sync(["Lib/**", "!Lib", "!Lib/ReadMe.md"]);
});
gulp.task("compress",
function (cb) {
pump([
gulp.src(paths.lib + "**/*.js"),
uglify(),
gulp.dest(paths.lib)
], cb);
});
gulp.task("copy",
function (cb) {
prefixPathToModules();
copyModules();
cb();
});
function prefixPathToModules() {
for (var moduleIndex in modules) {
for (var fileIndex in modules[moduleIndex]) {
modules[moduleIndex][fileIndex] = paths.bower + modules[moduleIndex][fileIndex];
}
}
}
function copyModules() {
for (var files in modules) {
gulp.src(modules[files], { base: paths.bower })
.pipe(gulp.dest(paths.lib));
}
}

You use run-sequence and your code
runSequence("clean", ["copy", "compress"], cb);
run in such order
clean
copy and compress in parallel // that's why your code compresses nothing, because you have not copied files yet
cb
Write like this and compress will be after copy
runSequence("clean", "copy", "compress", cb);

I am not familiar with runSequence. But why don't you try the following. By this way your default task depends on compress and compress depends on copy. So, 'copy' will run first and then 'compress'
gulp.task('default', ['copy','compress'], function(cb){});
gulp.task('compress',['copy'], function(cb){});
Gulp returns a steam , since you are calling it in a for loop the stream is returned during the first iteration itself.
Update your copyModule to the following and you can try either runSequence like posted by Kirill or follow my approach
function copyModules() {
var inputFileArr = [];
for (var files in modules) {
inputFileArr = inputFileArr.concat(modules[files]);
};
return gulp.src(inputFileArr, { base: paths.bower })
.pipe(gulp.dest(paths.lib));
}

Related

gulp task throwing error on second time run

I have two folders both of which contain some html template files. I need to minify these files to separate folders.
folder structure
|src
|--clientTemplates
|----abc.html
|----xyz.html
|--serverTemplates
|----abc.html
|----xyz.html
required destination folder
|dist
|--client
|----abc.html
|----xyz.html
|--server
|----abc.html
|----xyz.html
following is my gulpfile where I have my tasks defined for the
var gulp = require('gulp');
var htmlmin = require('gulp-htmlmin');
var replace = require('gulp-replace');
var del = require('del');
var minOptions = {
collapseWhitespace: true,
minifyJS: { output: { quote_style: 1 } },
minifyCSS: true
};
gulp.task('clean', function(done) {
del(['dist'], done());
});
gulp.task('minify:serverTemplates', function() {
return gulp
.src('src/serverTemplates/*.html')
.pipe(htmlmin(minOptions))
.pipe(replace('\\', '\\\\'))
.pipe(replace('"', '\\"'))
.pipe(gulp.dest('dist/server'));
});
gulp.task('minify:clientTemplates', function() {
return gulp
.src('src/clientTemplates/*.html')
.pipe(htmlmin(minOptions))
.pipe(gulp.dest('dist/client'));
});
gulp.task(
'default',
gulp.series('clean', 'minify:serverTemplates', 'minify:clientTemplates', function inSeries(done) {
done();
})
);
when I run the gulp command it works fine for the first time, but throws errors on alternate runs.
running gulp command first time
running gulp command second time
can't figure out what exactly is wrong there.
Also is there a way to run the two minification task parallel once the clean task has finished?
thanks for the help.
The callback you pass to del is wrong. Just return the promise:
gulp.task('clean', function() {
return del(['dist']);
});
As for running the minification tasks in parallel, use gulp.parallel:
gulp.task(
'default',
gulp.series(
'clean',
gulp.parallel('minify:serverTemplates', 'minify:clientTemplates')
)
);

Gulp and glob-stream task finishing too soon

I have a Gulp task that uses glob-stream to recursively loop through directories and files to perform a task, similar to below, but far more elaborate:
var gs = require('glob-stream');
var config = {
PATH: 'some/path/*.*'
}
function doSomething(filePath) {
var stream = gs.create(filePath);
// Do something
return gs.on('data', doSomething);
}
gulp.task('compile', function() {
var filePath = config.PATH;
return doSomething(filePath);
});
I can have the task achieve the results and compile what I need, but unfortunately Gulp believes the task has finished while it's still running, causing issues in my build process - How can I avoid this? I'm already using run-sequence but to no effect.
Why are you manually walking the directory tree with a recursive function? Why not just let glob-stream do the work for you? Then you only have to take care of the //Do something part:
var config = {
PATH: 'some/path/**' //glob pattern for all subfolder and files
};
function doSomething(filePath) {
//Do something
}
gulp.task('compile', function() {
var stream = gs.create(config.PATH);
stream.on('data', doSomething);
return stream;
});
gulp.task('secondTask', function() {
console.log('secondTask');
});
gulp.task('default', function() {
runSequence('compile', 'secondTask');
});
The some/path/** glob pattern creates a stream of all folders and files below some/path/, so you don't have to implement the recursive tree walk yourself.
Note that the compile task returns the stream. Otherwise gulp can't tell when the compile task has completed and starts running secondTask before compile has finished.

Gulp copies file but it is empty

I'm having a strange problem. I'm using gulp to compile a react app and am having it copy index.html to the appropriate web directory. When I first run gulp, all runs as expected, but when the file changes and the watch task is run, gulp copies an empty version of the file to the web directory. Does anyone know why this might be happening? Here is my gulpfile.js:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var livereload = require('gulp-livereload');
gulp.task('livereload', function() {
console.log('reloading');
livereload();
});
gulp.task('copyindextodist', function() {
gulp.src('app/index.html')
.pipe(gulp.dest('dist'));
});
gulp.task('compilejs', function() {
browserify({
entries: 'app/index.js',
extensions: ['.js'],
debug: true
})
.transform('babelify', {presets: ['es2015', 'react']})
.bundle()
.pipe(source('app.js'))
.pipe(gulp.dest('dist'));
});
gulp.task('publishapp', function() {
gulp.src('dist/*.*')
.pipe(gulp.dest('../public'));
});
gulp.task('copypaste', function() {
gulp.src('app/index.html')
.pipe(gulp.dest('../public'));
});
gulp.task('watch', function() {
livereload.listen();
gulp.watch('app/index.html', ['copyindextodist']);
gulp.watch('dist/index.html', ['publishapp']);
gulp.watch('app/index.js', ['compilejs']);
gulp.watch('dist/app.js', ['publishapp']);
});
gulp.task('default', ['copyindextodist', 'compilejs', 'publishapp', 'watch']);
I had the same problem until I defined the dependencies correctly. You can define which tasks should be completed, before the current task starts:
gulp.task('compress', ['copy'], function() {
//.... your job
});
This means that the compress task will wait for the copy task to be finished. If you don't do that, you might end up with empty/truncated files and other strange results.
Just take care that your copy tasks return a stream object.
gulp.task('copy', function() {
// "return" is the important part ;-)
return gulp.src(['filepath/**/*'])
.pipe(gulp.dest('lib/newpath'))
});
If you have multiple copy commands running in your task this is tricky, but there is an extension for this:
var gulp = require('gulp');
var merge = require('merge-stream');
gulp.task('copy', function() {
var allStreams = [
gulp.src(['node_modules/bootstrap/dist/**/*'])
.pipe(gulp.dest('lib/bootstrap')),
gulp.src(['node_modules/jquery/dist/**/*'])
.pipe(gulp.dest('lib/jquery')),
];
return merge.apply(this, allStreams);
});
gulp.task('nextTask', ['copy'], function() {
// this task formerly produced empty files, but now
// has a valid dependency on the copy stream and
// thus has all files available when processed.
});

Using gulp-minify-html and gulp-html-replace together

I am using Gulp with gulp-minify-html and gulp-html-replace:
var minifyhtml = require('gulp-minify-html');
var htmlreplace = require('gulp-html-replace');
var dev_paths = {
HTML: dev + '/**/*.html'
};
var prod_paths = {
RELATIVE_CSS: ['css/bootstrap.css', 'css/font-awesome.css', 'css/c3.css', 'css/main.css'],
};
//Compress HTML
gulp.task('minify-html', function () {
var opts = {
empty: true,
comments: true
};
return gulp.src(dev_paths.HTML)
.pipe(minifyhtml(opts))
.pipe(gulp.dest(prod + '/'));
});
//Add call to the JS and CSS in the HTML files
gulp.task('replace-files', function() {
gulp.src(dev_paths.HTML)
.pipe(htmlreplace({
'css': prod_paths.RELATIVE_CSS,
'js': 'js/script.js'
}))
.pipe(gulp.dest('public/prod/'));
});
gulp.task('prod',['replace-files','minify-html'], function(){
})
However, the HTML doesn't replace the CSS and JS files I specified with task replace-files. When I run gulp without the task minify-html, it works fine though.
Does anyone knows why using both tasks replace-files and minify-html together is not working?
Thank you.
As the tasks run in parallel it is likely the 'minify-html' task is running before the 'replace-files' task is complete.
Try using run-sequence to ensure the tasks run in the required order.

Determining if Gulp task called from another task

Is there a way to find out if a task been invoked directly or from another task?
runSequence = require 'run-sequence'
gulp.task 'build', ->
....
gulp.task 'run', ->
runSequence 'build', -> gulp.start('server')
I need an if case in build task that says:
if it was called directly - (gulp build) then do something;
or if it was invoked from run task then do something else
This might be an X/Y problem. What are you actually trying to accomplish?
But to answer the question; I think the only way is to look at the call stack trace and make sure only Gulp touches the task. I wrote a function that finds who orchestrated the task. You can just put the function inline with your gulpfile.js and use it like boolean.
The following code relies on npm parse-stack so make sure to npm install parse-stack
Usage: if(wasGulpTaskCalledDirectly()) { /*...*/ }
function wasGulpTaskCalledDirectly()
{
var parseStack = require("parse-stack");
var stack = parseStack(new Error());
// Find the index in the call stack where the task was started
var stackTaskStartIndex = -1;
for(var i = 0; i < stack.length; i++)
{
if(stack[i].name == 'Gulp.Orchestrator.start')
{
stackTaskStartIndex = i;
break;
}
}
// Once we find where the orchestrator started the task
// Find who called the orchestrator (one level up)
var taskStarterIndex = stackTaskStartIndex+1;
var isValidIndex = taskStarterIndex > 0 && taskStarterIndex < stack.length;
if(isValidIndex && /gulp\.js$/.test((stack[taskStarterIndex].filepath || "")))
{
return true;
}
return false;
}
You can find my full gulpfile.js used for testing below:
// This is a test for this SE question: http://stackoverflow.com/q/25928170/796832
// Figure out how to detect `gulp` vs `gulp build`
// Include gulp
var gulp = require('gulp');
var runSequence = require('run-sequence');
// Add this in from the above code block in the answer
//function wasGulpTaskCalledDirectly()
// ...
gulp.task('build', function() {
//console.log(wasGulpTaskCalledDirectly());
if(wasGulpTaskCalledDirectly())
{
// Do stuff here
}
else
{
// Do other stuff here
}
return gulp.src('./index.html', {base: './'})
.pipe(gulp.dest('./dist'));
});
// This does nothing
gulp.task('start-server', function() {
return gulp.src('./index.html', {base: './'});
});
// Default Task
gulp.task('default', function(callback) {
runSequence('build',
['start-server'],
callback
);
});