Gulp task running twice - javascript

After reading through a few related topics I still can't figure out what's causing gulp running a task twice.
This is the only task running twice:
const acf = "_sass/_admin/acf.scss";
const output = "./assets";
gulp.task("acf", () => {
return gulp.src(acf)
.pipe(plumber())
.pipe(sass())
.pipe(autoprefixer("last 2 versions", "> 5%"))
.pipe(concat("acf.min.css"))
.pipe(minify({ compatibility: '*' }))
.pipe(gulp.dest(output))
.pipe(browserSync.stream());
});
Another task which is handling a sibling file is running only once:
const gutenberg = "_sass/_admin/gutenberg.scss";
gulp.task("gutenberg", () => {
return gulp.src(gutenberg)
.pipe(plumber())
.pipe(sass())
.pipe(autoprefixer("last 2 versions", "> 5%"))
.pipe(concat("gutenberg.min.css"))
.pipe(minify({ compatibility: '*' }))
.pipe(gulp.dest(output))
.pipe(browserSync.stream());
});
Writing to the same DIR that another task is watching does not seem to be the issue.
See this handler:
gulp.task("default", done => {
browserSync.init({
open: false,
proxy: siteURL
});
gulp.watch(acf, gulp.series("acf"));
gulp.watch(gutenberg, gulp.series("gutenberg"));
done();
});
What am I missing? How do I make sure that the ACF task only runs once?

Related

Gulp isn't running tasks as expected

I'm writing a gulp file to build and concatenate JS files. The main purpose is to build ES6 code with Babel in a main.build.js, then concatenate additional libraries/dependencies in a main.deps.jsfile, and concatenate both files in a final main.bundle.js file. This is done for frontend and admin, so the output must be two files (main.bundle.js and admin.bundle.js).
To do that, I've created 3 tasks, and one to trigger all with one command. Here is my gulpfile.js code:
task("js:build", (done) => {
browserify({entries: path.resolve(srcPath, "js/main.js")})
.transform(babelify.configure({
presets: ["#babel/preset-env"]
}))
.bundle()
.on("error", (e) => {
console.error(e.message);
})
.pipe(source("main.build.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
browserify({entries: path.resolve(srcPath, "js/admin.js")})
.transform(babelify.configure({
presets: ["#babel/preset-env"]
}))
.bundle()
.on("error", (e) => {
console.error(e.message);
})
.pipe(source("admin.build.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
done();
});
task("js:deps", (done) => {
let mainDeps = jsDeps.main.map((asset) => {
return asset.indexOf("node_modules") > -1 ? asset : path.resolve(srcPath, "js/plugins", asset);
});
let adminDeps = jsDeps.admin.map((asset) => {
return asset.indexOf("node_modules") > -1 ? asset : path.resolve(srcPath, "js/plugins", asset);
});
if(mainDeps.length > 0){
src(mainDeps)
.pipe(plumber())
.pipe(concat("main.deps.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
}
if(adminDeps.length > 0){
src(adminDeps)
.pipe(plumber())
.pipe(concat("admin.deps.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
}
done();
});
task("js:concat", (done) => {
let mainDeps = path.resolve(distPath, "js/standalone/main.deps.js");
let mainBuild = path.resolve(distPath, "js/standalone/main.build.js");
let adminDeps = path.resolve(distPath, "js/standalone/admin.deps.js");
let adminBuild = path.resolve(distPath, "js/standalone/admin.build.js");
let main = fs.existsSync(mainDeps) ? [mainDeps, mainBuild] : [mainBuild];
let admin = fs.existsSync(adminDeps) ? [adminDeps, adminBuild] : [adminBuild];
src(main)
.pipe(plumber())
.pipe(concat("main.bundle.js"))
.pipe(dest(path.resolve(distPath, "js")));
src(admin)
.pipe(plumber())
.pipe(concat("admin.bundle.js"))
.pipe(dest(path.resolve(distPath, "js")));
done();
});
task("js", series("js:deps", "js:build", "js:concat"));
The problem is: when I run gulp js in my terminal, it throws an error that main.build.jsfile was not found, as if the js:build task hasn't executed. And, obviously, main.build.js isn't generated at desired folder.
But, for my surprise, if I run each task separately in my terminal (gulp js:deps, then gulp js:build, then gulp js:concat), it works like a charm, just like as expected. All .build and .deps file are generated and concatenated in .bundle files.
Looks like the gulp js:build isn't running when calling inside a series, or the series isn't running tasks in series (it's running like a parallel).
Can someone help me fixing that? Thanks!

Convert gulp watch in gulp#3.9.1 to gulp#4

We are switching from gulp#3.9.1 to gulp#4 and are having trouble switching over. When we run gulp watch, we are getting the following errors and trying to figure out how to resolve it.
What is the proper way to convert the gulp watch task to work with gulp#4?
Error message
AssertionError [ERR_ASSERTION]: Task never defined: minify-css
Command: gulp watch
This should run minify-js then minify-css in order
minify-js should run after clean-scripts has completed successfully
minify-css should run after clean-css has completed successfully
Current tasks.
var gulp = require('gulp'),
cssmin = require('gulp-clean-css'),
clean = require('gulp-clean'),
uglify = require('gulp-uglify');
var src = {
js: 'js/some-dir/**/*.js',
css: 'css/some-dir/**/*.css'
};
var dest = {
js: 'js/dest/some-dir/**/*.js',
css: 'css/dest/some-dir/**/*.css'
};
gulp.task('clean-css', function() {
return gulp.src(dest.css)
.pipe(clean({read:false, force: true});
});
gulp.task('minify-css', ['clean-css'], function() {
gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
});
gulp.task('clean-scripts', function() {
return gulp.src(dest.js)
.pipe(clean({read:false, force: true});
});
gulp.task('minify-js', ['clean-scripts'], function() {
gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
});
gulp.task('watch', ['minify-js', 'minify-css'], function() {
gulp.watch(src.js, ['minify-js']);
gulp.watch(src.css, ['minify-css']);
});
We tried doing this, but it resulted in the error message
gulp.task('watch', gulp.series('minify-js', 'minify-css', function() {
gulp.watch(src.js, ['minify-js']);
gulp.watch(src.css, ['minify-css']);
}));
gulp.task('minify-css', gulp.series('clean-css', function() {
return gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
}));
gulp.task('minify-js', gulp.series('clean-scripts', function() {
return gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
}));
gulp.task('watch', gulp.series('minify-js', 'minify-css', function() {
gulp.watch(src.js, gulp.series('minify-js'));
gulp.watch(src.css, gulp.series('minify-css'));
}));
As #Abdaylan suggested, I also advocate switching to functions. Nevertheless, so you can see where your code was wrong, I have fixed it here. Gulp 4 does not use this syntax:
gulp.task('someTask', ['task1', 'task2'], function () {}); // gulp 3
Gulp 4:
gulp.task('someTask', gulp.series('task1', 'task2', function () {})); // gulp 4 with string tasks
or gulp.parallel. So you can use your gulp.task syntax (rather than named functions) if you modify them to use the signatures that gulp 4 supports as I did in your modified code at the top of this answer.
Gulp 4 with named functions:
gulp.task(someTask, gulp.series(task1, task2, function () {})); // gulp 4 with named functions
So with named functions, the tasks are not referred to as strings.
See also task never defined for other potential problems when migrating from gulp3 to gulp4 with the same error message.
I would recommend converting your minify-js, minify-css, clean-scripts and clean-css tasks to functions:
var dest = {
js: 'js/dest/some-dir/**/*.js',
css: 'css/dest/some-dir/**/*.css'
};
function cleanCss() {
return gulp.src(dest.css)
.pipe(clean({read:false, force: true});
});
function minifyCss() {
return gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
});
function cleanScripts() {
return gulp.src(dest.js)
.pipe(clean({read:false, force: true});
});
function minifyJs() {
return gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
});
var minifyJsAndClean = gulp.series(minifyJs, cleanScripts);
var minifyCssAndClean = gulp.series(minifyCss, cleanCss);
var watchers = function (done) {
gulp.watch(src.js, minifyJs);
gulp.watch(src.css, minifyCss);
done();
}
gulp.task('watch', gulp.series(minifyJsAndClean, minifyCssAndClean, watchers));
I just ran into this a couple days ago myself. What worked for me was to run each task in its own gulp.watch() with the gulp.series() on the watch task call instead of the watch task itself. For example:
gulp.task('watch', function() {
gulp.watch(src.js, gulp.series('minify-js'));
gulp.watch(src.css, gulp.series('minify-css'));
});

Continue piping for gulp tasks after returning

I have two gulp tasks I need to run, one for js, one for css. I need them to run differently for build-dev (not minified) and build-prod (minified).
To do this, I stripped out the minification and gulp.dest portions of the tasks for js and css and am instead returning gulp.src to the tasks build-prod or build-dev. These two tasks build-prod or build-dev are now responsible for manipulating the js and css tasks differently.
How can I return the tasks' gulp.src to build-prod or build-dev for continued piping?
Note: since it's a stream, it seems I'm returning the stream after the last pipe finishes for that task, then since it's asynchronous, why can't I chain pipes after gulp.src returns?
gulp.task('css', function() {
return gulp.src('css/**.css')
.pipe(autoprefixer('last 10 version'))
.pipe(concatCss('main.css'));
// .pipe(minifycss())
// .pipe(gulp.dest('build/css'));
});
gulp.task('js', ...
return gulp.src(['./js/**/*.js'])
.pipe(
... // Huge function that I don't want to duplicate
});
gulp.task('build-prod', function() {
gulp.run('css')
.pipe(minifycss())
.pipe(gulp.dest('build/css'));
gulp.run('scripts')
.pipe(minifyjs())
.pipe(gulp.dest('build/js'));
});
gulp.task('build-dev', function() {
gulp.run('css')
.pipe(gulp.dest('build/css'));
gulp.run('scripts')
.pipe(gulp.dest('build/js'));
});
Why not make a function you call in multiple places?
function cssTask() {
return gulp.src('css/**.css')
.pipe(autoprefixer('last 10 version'))
.pipe(concatCss('main.css'));
}
gulp.task('css', function () {
return cssTask();
});
gulp.task('build-prod', function () {
cssTask()
.pipe(minifycss())
.pipe(gulp.dest('build/css'));
});
gulp.task('build-dev', function () {
cssTask()
.pipe(gulp.dest('build/css'));
});
The best way is to use gulp conditionals: .pipe(gulpif(isProduction, minifycss()))
Gulp If is a great way to do it.
let isProduction = false;
...
gulp.task('css', function() {
return gulp.src('css/**.css')
.pipe(autoprefixer('last 10 version'))
.pipe(concatCss('main.css'))
.pipe(gulpif(isProduction, minifycss())) // conditional
.pipe(gulp.dest('build/css'));
});
gulp.task('build-prod', function() {
isProduction = true;
gulp.run('css');
});
gulp.task('build-dev', function() {
isProduction = false;
gulp.run('css');
});

My gulp task to "concat" and "dest" my .css file, is only running if I run 2 times

The concatenation and destination to my public/assets/css is only working if i run 2 times the task. Even if I run just the app.css (npm run dev app.css), only work if I run twice.
const gulp = require('gulp')
const htmlmin = require('gulp-htmlmin')
const uglify = require('gulp-uglify')
const uglifycss = require('gulp-uglifycss')
const concat = require('gulp-concat')
const babel = require('gulp-babel')
const sass = require('gulp-sass')
gulp.task('app', ['app.html', 'app.sass', 'app.js', 'app.assets', 'app.css'])
gulp.task('app.html', function(){
gulp.src(['app/**/*.html'])
.pipe(htmlmin({ collapseWhitespace: true, removeComments: true}))
.pipe(gulp.dest('public'))
})
gulp.task('app.sass', function () {
gulp.src(['sass/main.scss'])
.pipe(sass.sync().on('error', sass.logError))
.pipe(gulp.dest('app/css'))
});
gulp.task('app.css', function(){
gulp.src(['app/**/*.css'])
.pipe(uglifycss({ "uglyComments": true}))
.pipe(concat('app.min.css'))
.pipe(gulp.dest('public/assets/css'))
})
gulp.task('app.js', function(){
gulp.src(['app/**/*.js'])
.pipe(babel({ presets: ['es2015'] }))
.pipe(uglify())
.pipe(concat('app.min.js'))
.pipe(gulp.dest('public/assets/js'))
})
gulp.task('app.assets', function(){
gulp.src(['assets/**/*.*'])
.pipe(gulp.dest('public/assets'))
})
For gulp to respect the order of the task dependencies you defined, you need to tell it when the task is done.
To do so, you need to return a stream, a promise, or call the task function callback parameter.
Since your tasks are pretty basic, just returning the stream should be enough.
gulp.task('app.sass', function () {
return gulp.src(['sass/main.scss']) // notice the return here
.pipe(sass.sync().on('error', sass.logError))
.pipe(gulp.dest('app/css'));
});
// make the sass task a dependency of the CSS task
gulp.task('app.css', ['app.sass'], function(){
return gulp.src(['app/**/*.css']) // notice the return here
.pipe(uglifycss({ "uglyComments": true}))
.pipe(concat('app.min.css'))
.pipe(gulp.dest('public/assets/css'));
});
Now you don't need the app.sass since it will run before app.css.
gulp.task('app', ['app.html', 'app.js', 'app.assets', 'app.css'])
I think that your tasks should be waiting for a result from the previous task. You can't just run several tasks in one time.
Try with gulp-sequence plugin. Install gulp-sequence and add the following line on the top of your gulpfile.js:
const gulpSequence = require('gulp-sequence')
Replace your current 'app' task by:
gulp.task('app', gulpSequence('app.html', 'app.sass', 'app.js', 'app.assets', 'app.css'))

Using Jade features with gulp-changed?

When I make changes to .jade files I want to Gulp task run only for that file, not for all files. For that I'm using gulp-changed. It's working fine, until I make changes to files that affect to global layout, eg _header.jade, _layout.jade. When I make changes to that files nothing happens. All my layout files have _ before title. How can I solve this issue?
Here is my gulpfile some lines
gulp.task('jade', function() {
return gulp.src('dev/templates/**/!(_)*.jade')
.pipe(plumber({
errorHandler: onError
}))
.pipe(changed('public', {extension: '.html'}))
.pipe(jade({
pretty: true,
}))
.pipe(gulp.dest('public'))
.pipe(browserSync.reload({
stream: true
}));
});
gulp.task('watch', function() {
gulp.watch('dev/templates/**/*.jade', gulp.series('jade'));
});
First thing I would do is to refactor out your jade compilation task into a separate function. That allows you to parameterize your jade compilation so that you can run it on one or more files of your choice:
function compileJade(files) {
return gulp.src(files, {base:'dev/templates'})
.pipe(plumber({
errorHandler: onError
}))
.pipe(jade({
pretty: true,
}))
.pipe(gulp.dest('public'))
.pipe(browserSync.reload({
stream: true
}));
}
Your existing jade task now simply calls that function:
gulp.task('jade', function() {
return compileJade('dev/templates/**/!(_)*.jade');
});
If a changed file is a partial (starts with _) we need to be able to determine which other files are affected by that change. This is facilitated by the jade-inheritance library:
var JadeInheritance = require('jade-inheritance');
var path = require('path');
function isPartial(file) {
return path.basename(file).match(/^_.*/);
}
function findAffectedFiles(changedFile) {
return new JadeInheritance(changedFile, 'dev/templates', {basedir: 'dev/templates'})
.files
.filter(function(file) { return !isPartial(file); })
.map(function(file) { return 'dev/templates/' + file; })
}
Finally whenever a file changes we call the compileJade function for the affected files only:
gulp.task('watch', function() {
gulp.watch('dev/templates/**/*.jade').on('change', function(changedFile) {
return compileJade(isPartial(changedFile) ? findAffectedFiles(changedFile) : changedFile);
});
});

Categories