Gulp v4 watch task
Asked Answered
V

5

11


I just upgraded to Gulp v4 and was wondering why my gulpfile isn't working anymore.
I tried the new code of the new documentation but it didn't worked out as planned because I'm using "pure" postcss.
So I googled for my issue and found this question: Gulp error: watch task has to be a function
However, this also wasnt a solution for my problem, although I get the same error message Error: watching src/styles/**/*.scss: watch task has to be a function

I currently have this code

var gulp = require('gulp');
var sass = require('gulp-sass');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var cssnano = require('cssnano');

gulp.task('default', function () {
    gulp.watch('src/styles/**/*.scss', ['styles']);
});

gulp.task('styles', function () {
    var processors = [
        autoprefixer({
            browsers: ['last 3 versions', 'ie > 9']
        }),
        cssnano()
    ];
    gulp.src('src/styles/main.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss(processors))
        .pipe(gulp.dest('dist/files/styles/'));
});

and when I change
gulp.watch('src/styles/**/*.scss', ['styles']);
to
gulp.watch('src/styles/**/*.scss', gulp.series('styles'));
it just gives me a Starting 'default'... and after changing a file Starting 'styles'...
with Gulp 3.9 it was

Starting 'default'...
Finished 'default' after 174 ms

and after changing a file

Starting 'styles'...
Finished 'styles' after 561 μs

I've now tried many different things but I just dont get it to work like it did before. I'm really thinking of switching over to webpack like the cool kids now. But Gulp always worked fine.

Can someone explain to me what I'm doing wrong?

Volvulus answered 30/8, 2018 at 10:52 Comment(0)
V
9

After reading the documentation and, more importantly, understanding it, I was able to figure it out myself.

const autoprefixer = require('autoprefixer');
const babel = require('gulp-babel');
const cssdeclarationsorter = require('css-declaration-sorter');
const cssnano = require('cssnano');
const gulp = require('gulp');
const postcss = require('gulp-postcss');
const rename = require('gulp-rename');
const sass = require('gulp-sass');
const uglify = require('gulp-uglify');

const paths = {
    'styles': {
        'base': 'src/styles/',
        'src': 'src/styles/main.scss',
        'dest': 'dist/styles/',
        'watch': 'src/styles/**/*.scss',
    },
    'scripts': {
        'base': 'src/scripts/',
        'src': 'src/scripts/**/*.js',
        'dest': 'dist/scripts/',
        'watch': 'src/scripts/**/*.js',
    },
};

const styles = function () {
    const plugins = [
        autoprefixer(),
        cssdeclarationsorter(),
        cssnano(),
    ];

    return gulp.src(
        paths.styles.src,
        {
            'base': paths.styles.base,
        }
    ).
        pipe(sass().on(
            'error',
            sass.logError
        )).
        pipe(postcss(plugins)).
        pipe(rename({
            'basename': 'styles',
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.styles.dest));
};

const scripts = function () {
    return gulp.src(
        paths.scripts.src,
        {
            'base': paths.scripts.base,
        }
    ).
        pipe(babel()).
        pipe(uglify()).
        pipe(rename({
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.scripts.dest));
};

const watch = function () {
    gulp.watch(
        paths.scripts.watch,
        scripts
    );
    gulp.watch(
        paths.styles.watch,
        styles
    );
};

const build = gulp.parallel(
    styles,
    scripts,
    gulp.series(watch)
);

exports.default = build;

And for module

import autoprefixer from 'autoprefixer';
import babel from 'gulp-babel';
import cssdeclarationsorter from 'css-declaration-sorter';
import cssnano from 'cssnano';
import gulp from 'gulp';
import postcss from 'gulp-postcss';
import rename from 'gulp-rename';
import sass from 'gulp-sass';
import uglify from 'gulp-uglify';

const paths = {
    'styles': {
        'base': 'src/styles/',
        'src': 'src/styles/main.scss',
        'dest': 'dist/styles/',
        'watch': 'src/styles/**/*.scss',
    },
    'scripts': {
        'base': 'src/scripts/',
        'src': 'src/scripts/**/*.js',
        'dest': 'dist/scripts/',
        'watch': 'src/scripts/**/*.js',
    },
};

export const styles = function () {
    const plugins = [
        autoprefixer(),
        cssdeclarationsorter(),
        cssnano(),
    ];

    return gulp.src(
        paths.styles.src,
        {
            'base': paths.styles.base,
        }
    ).
        pipe(sass().on(
            'error',
            sass.logError
        )).
        pipe(postcss(plugins)).
        pipe(rename({
            'basename': 'styles',
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.styles.dest));
};

export const scripts = function () {
    return gulp.src(
        paths.scripts.src,
        {
            'base': paths.scripts.base,
        }
    ).
        pipe(babel()).
        pipe(uglify()).
        pipe(rename({
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.scripts.dest));
};

export const watch = function () {
    gulp.watch(
        paths.scripts.watch,
        scripts
    );
    gulp.watch(
        paths.styles.watch,
        styles
    );
};

const build = gulp.parallel(
    styles,
    scripts,
    gulp.series(watch)
);

export default build;
Volvulus answered 30/8, 2018 at 14:37 Comment(1)
Are you sure this is valid Gulp v4 syntax? You are not using built-in exports variable for declaring and exposing tasks.Instanter
C
20

I struggled with this one myself..

took me hours of headache only to find out that basically everything changes with v4.0

I've run my code like this and it works perfectly...

//Do everything once!
  gulp.task('default', function(){
    gulp.watch('src/styles/*.css', gulp.series('css')),
    gulp.watch('src/html/*.html', gulp.series('copyHTML')),
    gulp.watch('src/js/*.js', gulp.series('scripts')),
    gulp.watch('src/images/*', gulp.series('imageMIN'));
  return
});
Castle answered 3/1, 2019 at 21:51 Comment(1)
The key is gulp.series part.Afra
V
9

After reading the documentation and, more importantly, understanding it, I was able to figure it out myself.

const autoprefixer = require('autoprefixer');
const babel = require('gulp-babel');
const cssdeclarationsorter = require('css-declaration-sorter');
const cssnano = require('cssnano');
const gulp = require('gulp');
const postcss = require('gulp-postcss');
const rename = require('gulp-rename');
const sass = require('gulp-sass');
const uglify = require('gulp-uglify');

const paths = {
    'styles': {
        'base': 'src/styles/',
        'src': 'src/styles/main.scss',
        'dest': 'dist/styles/',
        'watch': 'src/styles/**/*.scss',
    },
    'scripts': {
        'base': 'src/scripts/',
        'src': 'src/scripts/**/*.js',
        'dest': 'dist/scripts/',
        'watch': 'src/scripts/**/*.js',
    },
};

const styles = function () {
    const plugins = [
        autoprefixer(),
        cssdeclarationsorter(),
        cssnano(),
    ];

    return gulp.src(
        paths.styles.src,
        {
            'base': paths.styles.base,
        }
    ).
        pipe(sass().on(
            'error',
            sass.logError
        )).
        pipe(postcss(plugins)).
        pipe(rename({
            'basename': 'styles',
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.styles.dest));
};

const scripts = function () {
    return gulp.src(
        paths.scripts.src,
        {
            'base': paths.scripts.base,
        }
    ).
        pipe(babel()).
        pipe(uglify()).
        pipe(rename({
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.scripts.dest));
};

const watch = function () {
    gulp.watch(
        paths.scripts.watch,
        scripts
    );
    gulp.watch(
        paths.styles.watch,
        styles
    );
};

const build = gulp.parallel(
    styles,
    scripts,
    gulp.series(watch)
);

exports.default = build;

And for module

import autoprefixer from 'autoprefixer';
import babel from 'gulp-babel';
import cssdeclarationsorter from 'css-declaration-sorter';
import cssnano from 'cssnano';
import gulp from 'gulp';
import postcss from 'gulp-postcss';
import rename from 'gulp-rename';
import sass from 'gulp-sass';
import uglify from 'gulp-uglify';

const paths = {
    'styles': {
        'base': 'src/styles/',
        'src': 'src/styles/main.scss',
        'dest': 'dist/styles/',
        'watch': 'src/styles/**/*.scss',
    },
    'scripts': {
        'base': 'src/scripts/',
        'src': 'src/scripts/**/*.js',
        'dest': 'dist/scripts/',
        'watch': 'src/scripts/**/*.js',
    },
};

export const styles = function () {
    const plugins = [
        autoprefixer(),
        cssdeclarationsorter(),
        cssnano(),
    ];

    return gulp.src(
        paths.styles.src,
        {
            'base': paths.styles.base,
        }
    ).
        pipe(sass().on(
            'error',
            sass.logError
        )).
        pipe(postcss(plugins)).
        pipe(rename({
            'basename': 'styles',
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.styles.dest));
};

export const scripts = function () {
    return gulp.src(
        paths.scripts.src,
        {
            'base': paths.scripts.base,
        }
    ).
        pipe(babel()).
        pipe(uglify()).
        pipe(rename({
            'suffix': '.min',
        })).
        pipe(gulp.dest(paths.scripts.dest));
};

export const watch = function () {
    gulp.watch(
        paths.scripts.watch,
        scripts
    );
    gulp.watch(
        paths.styles.watch,
        styles
    );
};

const build = gulp.parallel(
    styles,
    scripts,
    gulp.series(watch)
);

export default build;
Volvulus answered 30/8, 2018 at 14:37 Comment(1)
Are you sure this is valid Gulp v4 syntax? You are not using built-in exports variable for declaring and exposing tasks.Instanter
T
2

Can be used via event

function watch() {
    const watcher = gulp.watch('src/styles/**/*.scss');
    watcher.on('change', function(path, stats) {
        styles(); //styles task
    });
}

exports.default = gulp.series(watch);
Timothytimour answered 6/4, 2019 at 4:23 Comment(0)
F
1

Just in case anyone else stumbles on this (like I did), trying to solve Gulp not working after upgrading, I found there were really only two things that mattered for me (after trying hundreds) -

  1. "\\" for path separators no longer works on Windows. "/" is the only way to go. This was the longest pain point for me. Probably better to do it this way anyway, because it makes it cross platform - but I was on a Windows only project at the time.
  2. Make sure to emit a callback if you are calling tasks series or return a promise. It was not obvious to me exactly when that was required, and leaving it out was causing me major pain. It's something like this:
gulp.task('js', (done) => {
    gulp.src(src)
        .pipe(task())
        .pipe(task(etc))
        //etc
        .pipe(gulp.dest(dst));
    done();
});

I'm specifically using the old style in my example above to demonstrate that it really doesn't matter how you do it. Gulp is very forgiving, but it is a stickler about the callbacks and the paths. I think the paths thing is actually related to chokidar or some sub module that gulp is using.

Hope this saves someone some pain.

Fluviatile answered 22/2, 2020 at 17:40 Comment(0)
P
1

For my ionic v1 project (I know, it's obsolete now), I had to change the gulp file to below to keep in sync with v4 changes. Note that each of the tasks that you want to watch have to be predefined (special caution for hoisting if you're using ES6):

var gulp = require('gulp');
var sass = require('gulp-sass');
var cleanCss = require('gulp-clean-css');
var rename = require('gulp-rename');

var paths = {
  sass: ['./scss/**/*.scss']
};

gulp.task('sass', function(done) {
  gulp.src('./scss/*.scss')
    .pipe(sass())
    .on('error', sass.logError)
    .pipe(gulp.dest('./www/css/'))
    .pipe(cleanCss({
      keepSpecialComments: 0
    }))
    .pipe(rename({extname: '.min.css'}))
    .pipe(gulp.dest('./www/css/'))
    .on('end', done);
});

gulp.task('watch', function () {
  gulp.watch(paths.sass, gulp.series('sass'));
});

gulp.task('default', gulp.series('watch'));

and then you can watch by just running gulp in CLI (which causes it to run gulp default, which in turn runs gulp watch, which watches for any changes in any scss files in the given directory and runs sass task for every change)

Photoconductivity answered 20/4, 2020 at 18:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.