I'd like to create a watcher to watch some files and compile them.
I have two tasks :
minCss
compile
I'd like to execute compile in first and wait the end before executing minCss... But it seem's not working.
My code :
var scssToCompile = [
'./public/sass/themes/adms/adms.scss',
'./public/sass/themes/arti/arti.scss',
'./public/sass/themes/avantage/avantage.scss',
'./public/sass/themes/basique/basique.scss',
'./public/sass/themes/mairie/mairie.scss',
'./public/sass/themes/vehik/vehik.scss',
'./public/sass/themes/concept/concept.scss',
'./public/sass/themes/news/news.scss',
'./public/sass/components/*.scss',
'./public/sass/_functions.scss',
'./public/sass/_settings.scss',
'./public/sass/app.scss',
'./public/sass/bottom.scss'
];
gulp.task('compile', function(){
return gulp.src(scssToCompile)
.pipe(sassGlob())
.pipe(sass({includePaths: ['./public/sass']}).on('error', function(err) {
cb(err);
}))
.pipe(gulp.dest('./public/stylesheets'));
});
gulp.task('minCss', function() {
return gulp.src('public/stylesheets/themes/**/*.css')
.pipe(minifyCss())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('public/build/css'));
});
// my watcher
gulp.task('watch', function(){
gulp.watch(scssToCompile, ['compile', 'minCss']);
});
Results :
[15:21:36] Using gulpfile C:\xampp\htdocs\gulpfile.js
[15:21:36] Starting 'watch'...
[15:21:37] Finished 'watch' after 153 ms
[15:21:41] Starting 'compile'...
[15:21:46] Starting 'minCss'...
[15:21:46] Finished 'minCss' after 6.42 μs
[15:21:48] Finished 'compile' after 6.44 s
Related
I have a problem with my gulp, I don't know how to explain it, but you will understand the problem when you see it, basically, I think my gulp is duplicating the task and therefore the execution can take a while, but if I finish the gulp and execute it again, the problem does not happen the first time it is compiled, but over time it is repeated more and more (first doubles, then 4x, 8x and so on)
my gulp:
var gulp = require('gulp'),
//Js
babel = require('gulp-babel');
uglify = require('gulp-uglify'),
filesJs = './js/edit/*.js',
outputJs = './js',
//Sass
sass = require('gulp-sass'),
filesCss = './css/**/*.+(scss|sass)',
outputCss = './css';
const {
watch
} = require('gulp');
//Uglify
gulp.task('uglify', function () {
gulp.src(filesJs)
.pipe(babel({presets: ['#babel/preset-env']}))
.pipe(uglify())
.pipe(gulp.dest(outputJs));
});
const watcherJS = watch([filesJs]);
watcherJS.on('change', function (path, stats) {
console.log(`File ${path} was changed`);
return gulp.watch(filesJs, gulp.series('uglify'));
});
//Sass
gulp.task('sass', function () {
return gulp.src(filesCss)
.pipe(sass({
outputStyle: 'compressed'
}).on('error', sass.logError))
.pipe(gulp.dest(outputCss));
});
const watcherCSS = watch([filesCss]);
watcherCSS.on('change', function (path, stats) {
console.log(`File ${path} was changed`);
return gulp.watch(filesCss, gulp.series('sass'));
});
//Run/Watch
gulp.task('default', gulp.parallel('uglify', 'sass'));
my terminal after a save the .sass file once
File css\style.sass was changed
[09:43:18] Starting 'sass'...
[09:43:18] Starting 'sass'...
[09:43:18] Starting 'sass'...
[09:43:18] Starting 'sass'...
[09:43:33] Finished 'sass' after 15 s
[09:43:33] Finished 'sass' after 15 s
[09:43:33] Finished 'sass' after 15 s
[09:43:33] Finished 'sass' after 15 s
It is almost certainly your use of the chokidar watch functionality. Your code won't even run for me. And you don't need that complexity. I suggest getting rid of
const watcherJS = watch([filesJs]);
watcherJS.on('change', function (path, stats) {
console.log(`File ${path} was changed`);
return gulp.watch(filesJs, gulp.series('uglify')); // this is very strange, must be wrong
});
const watcherCSS = watch([filesCss]);
watcherCSS.on('change', function (path, stats) {
console.log(`File ${path} was changed`);
return gulp.watch(filesCss, gulp.series('sass'));
});
and replacing with:
gulp.task('watchFiles', function () {
gulp.watch(filesCss, gulp.series('sass'));
gulp.watch(filesJs, gulp.series('uglify'));
});
and using
gulp.task('default', gulp.series('uglify', 'sass', 'watchFiles'));
I've got this gulp file
const gulp = require('gulp')
const sass = require('gulp-sass')
const cleanCSS = require('gulp-clean-css')
const rimraf = require('rimraf')
const concat = require('gulp-concat')
gulp.task('clean', function(cb) {
rimraf('./dist/*', cb)
})
gulp.task('sass', function(cb) {
gulp.src('./src/**/*.scss')
.pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError))
.pipe(gulp.dest('./dist'))
console.log('before')
cb(undefined)
})
gulp.task('minify', function(cb) {
gulp.src('./src/**/*.css')
.pipe(cleanCSS())
.pipe(gulp.dest('./dist'))
console.log('before')
cb(undefined)
})
gulp.task('build:css', ['sass', 'minify'], function() {
gulp.src('./dist/**/*.css')
.pipe(concat('style.min.css'))
.pipe(gulp.dest('./dist'))
console.log('after')
})
gulp.task('build', ['clean'], function() {
gulp.start('build:css')
})
gulp.task('build:watch', function () {
gulp.watch('./src/**/*.scss', ['build'])
})
But when I run build:watch
[11:26:18] Using gulpfile C:\dev\web\ikea_design\gulpfile.js
[11:26:18] Starting 'build:watch'...
[11:26:18] Finished 'build:watch' after 16 ms
[11:26:24] Starting 'clean'...
[11:26:24] Finished 'clean' after 11 ms
[11:26:24] Starting 'build'...
[11:26:24] Starting 'sass'...
before
[11:26:24] Finished 'sass' after 12 ms
[11:26:24] Starting 'minify'...
before
[11:26:24] Finished 'minify' after 2.27 ms
[11:26:24] Starting 'build:css'...
after
[11:26:24] Finished 'build:css' after 1.16 ms
[11:26:24] Finished 'build' after 25 ms
even if it displays the two befores before the after, style.css.min doesn't get created. That's strange since the css files should have already been saved in the dist folder by the time concat gets invoked.
What's wrong?
Edit
I've run gulp-debug inside of build:css and it shows 0 items in the pipe
So I'm trying to compile pug (jade), javascript and sass files with Gulp V4, and using browserSync to reload the browser when any of these files change. There are a lot of guides out there, but no matter which way I write the code, it just doesn't seem to get the task order right. Im using gulp.series to set the task order, but browserSync doesn't want to play ball.
Here's a print of my Gulp file:
var gulp = require('gulp'),
... etc.
var paths = {
sass: ['src/scss/**/*.scss'],
js: ['src/js/**/*.js'],
pug: ['src/**/*.pug']
};
// Shared Tasks:
//*------------------------------------*/
gulp.task('clean', function(done){
del(['dist/assets/**/*.css', 'dist/assets/**/*.map', 'dist/assets/**/*.js']);
done();
});
// App Specific Tasks:
//*------------------------------------*/
// Sass
gulp.task('build-sass', function(){
gulp.src(paths.sass)
return sass(paths.sass, {
style: 'expanded'
})
.on('error', sass.logError)
.pipe(prefix('last 2 version', '> 1%', 'ie 8', 'ie 9'))
.pipe(sourcemaps.write())
.pipe(gulp.dest('dist/assets/css'))
.pipe(cleanCSS({ advanced: false, keepSpecialComments: 0 }))
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('dist/assets/css'));
});
// JS
gulp.task('build-js', function(done){
gulp.src(paths.js)
.pipe(concat('all.js'))
.pipe(gulp.dest('dist/assets/js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('dist/assets/js'))
done();
// Pug
gulp.task('build-pug', function buildHTML(done){
gulp.src(['src/**/*.pug'], {
base: 'src'
})
.pipe(pug())
.pipe(gulp.dest('./dist/'))
done();
});
// Service Tasks:
//*------------------------------------*/
// Delete the compiled views dir.
gulp.task('remove', function(done){
del(['dist/views/**/']);
done();
});
// Serve the site locally and watch for file changes
gulp.task('serve', function(done){
browserSync.init({
server: {
baseDir: './dist/',
notify: false,
open: false
}
});
// Watch & Reload Pug Files
gulp.watch([paths.pug], gulp.series('build-pug')).on('change', browserSync.reload);
// Watch & Reload Sass Files
gulp.watch([paths.sass], gulp.series('build-sass')).on('change', browserSync.reload);
});
gulp.task('default', gulp.series('clean', 'build-sass', 'build-js', 'build-pug', 'remove', 'serve', function(done){
done();
}));
And the terminal console log outputs this when starting gulp:
$ gulp
[13:09:33] Using gulpfile ~/Dropbox Aaron/Dropbox (Personal)/01_Me/01_Dev/01_My Work/*Template/gulpfile.js
[13:09:33] Starting 'default'...
[13:09:33] Starting 'clean'...
[13:09:33] Finished 'clean' after 2.64 ms
[13:09:33] Starting 'build-sass'...
[13:09:33] Finished 'build-sass' after 443 ms
[13:09:33] Starting 'build-js'...
[13:09:33] Finished 'build-js' after 4.42 ms
[13:09:33] Starting 'build-pug'...
[13:09:33] Finished 'build-pug' after 3.15 ms
[13:09:33] Starting 'remove'...
[13:09:33] Finished 'remove' after 656 μs
[13:09:33] Starting 'serve'...
[BS] Access URLs:
-------------------------------------
Local: http://localhost:3000
External: http://10.130.91.51:3000
-------------------------------------
UI: http://localhost:3001
UI External: http://10.130.91.51:3001
-------------------------------------
[BS] Serving files from: ./dist/
And this when I change a file within the watched files:
[BS] File changed: src/scss/4_elements/_elements.page.scss
[13:12:33] Starting 'build-sass'...
[13:12:34] write ./style.css
[13:12:34] Finished 'build-sass' after 366 ms
So what seems to me to be happening in this instance, the file is changing, browserSync reloads the page, and then 'build-sass' starts. Which is the wrong way round. I obviously want to build the sass, then reload the page. I have to save 2 times for the browser to refresh the code I want.
Some of the code I've used is directly from the browserSync documentation:
https://www.browsersync.io/docs/gulp#gulp-reload
This doesn't seem to work.
Your log output looks right. First it runs 'default' and then your series of tasks. Later when you modify a sass file, it starts 'build-sass'. The only problem is it doesn't reload via browserSync.reload(). So I believe the problem may be here:
gulp.watch([paths.sass], gulp.series('build-sass')).on('change', browserSync.reload);
I highly recommend
https://github.com/gulpjs/gulp/blob/4.0/docs/recipes/minimal-browsersync-setup-with-gulp4.md
that is the gulp4.0 recipe to do exactly what you are trying to do. I am using pretty much what they have there, so if you have problems getting their code to work I can help. Here is my working code:
function serve (done) {
browserSync.init({
server: {
baseDir: "./",
index: "home.html"
},
ghostMode: false
});
done();
}
function reload(done) {
browserSync.reload();
done();
}
var paths = {
styles: {
src: "./scss/*.scss",
dest: "./css"
},
scripts: {
src: "./js/*.js",
dest: "./js"
}
};
function watch() {
gulp.watch(paths.scripts.src, gulp.series(processJS, reload));
gulp.watch(paths.styles.src, gulp.series(sass2css, reload));
gulp.watch("./*.html").on("change", browserSync.reload);
}
var build = gulp.series(serve, watch);
gulp.task("sync", build);
function sass2css() {
return gulp.src("./scss/*.scss")
.pipe(cached("removing scss cached"))
// .pipe(sourcemaps.init())
.pipe(sass().on("error", sass.logError))
// .pipe(sourcemaps.write("./css/sourceMaps"))
.pipe(gulp.dest("./css"));
}
function processJS() {
return gulp.src("./js/*.js")
.pipe(sourcemaps.init())
// .pipe(concat("concat.js"))
// .pipe(gulp.dest("./concats/"))
// .pipe(rename({ suffix: ".min" }))
// .pipe(uglify())
.pipe(sourcemaps.write("./js/sourceMaps/"))
.pipe(gulp.dest("./js/maps/"));
}
Note the general use of functions instead of 'tasks' and particularly the reload(done) function. You might try simply adding that to your watch statements like
gulp.watch([paths.sass], gulp.series('build-sass', reload);
after you have added the reload function, that might be enough to fix your problem without making all the other changes as in my code. Or you might simply have to add a return statement to your 'build-sass' task so gulp knows that task has completed. Good luck.
I have set up gulp so that it will reload when the gulpfile is modified. That basic process is working, but for some reason it seems the old tasks are not being terminated properly.
var gulp = require('gulp');
var less = require('gulp-less');
var spawn = require('child_process').spawn;
gulp.task('default', function(){
var p;
if(p)
p.kill();
p = spawn('gulp', ['watch'], {stdio: 'inherit'});
});
gulp.task('watch', ['styles', 'watch-styles', 'watch-gulp']);
gulp.task('styles', function(){
return gulp.src('./**/*.less')
.pipe(less())
.pipe(gulp.dest('./'))
});
gulp.task('watch-styles', ['styles'], function(){
gulp.watch('./**/*.less', ['styles']);
});
gulp.task('watch-gulp', ['styles'], function(){
gulp.watch('./gulpfile.js', ['default']);
});
That is a basic gulpfile that demonstrates the problem. When I tweak that gulpfile to cause it to reload I receive this in the console:
[11:21:02] Starting 'default'...
[11:21:02] Finished 'default' after 5.25 ms
[11:21:02] Using gulpfile ~/repo/gulp-reload/gulpfile.js
[11:21:02] Starting 'styles'...
[11:21:02] Finished 'styles' after 34 ms
[11:21:02] Starting 'watch-styles'...
[11:21:03] Finished 'watch-styles' after 669 ms
[11:21:03] Starting 'watch-gulp'...
[11:21:03] Finished 'watch-gulp' after 1.83 ms
[11:21:03] Starting 'watch'...
[11:21:03] Finished 'watch' after 2.92 μs
Then modifying a less file within the directory gives this output
[11:21:24] Starting 'styles'...
[11:21:24] Finished 'styles' after 8.95 ms
[11:21:24] Starting 'styles'...
[11:21:24] Finished 'styles' after 2.92 ms
Each subsequent restart seems to lead to an additional call to styles, as if the old watchers are still there.
I created a small repo on Github with this example project as well.
In this task:
gulp.task('default', function(){
var p;
if(p)
p.kill();
p = spawn('gulp', ['watch'], {stdio: 'inherit'});
});
p is never defined, because you always create a new variable when you call that function. Also, you don't have a pointer to your own process which you want to kill. A safer way would be to end all the other watchers by hand:
gulp.task('watch-styles', ['styles'], function(){
var watcher = gulp.watch('./**/*.less', ['styles']);
watchers.push(watcher);
});
gulp.task('watch-gulp', ['styles'], function(){
var watcher = gulp.watch('./gulpfile.js', ['default']);
watchers.push(watcher);
watcher.on('change', function(){
watchers.forEach(function(el){
el.end();
})
})
});
Everytime I run my gulp task, it generates a error on first run. The error is below. When I run it again, it builds without any error.
I am confused, why does it throw an error the first time but not after that.
[08:38:08] Using gulpfile ~/Documents/Code/proj2/Gulpfile.js
[08:38:08] Starting 'stylus'...
[08:38:08] Finished 'stylus' after 7.99 ms
[08:38:08] Starting 'copyClientHTML'...
[08:38:08] Finished 'copyClientHTML' after 2.27 ms
[08:38:08] Starting 'clientLint'...
[08:38:08] Starting 'demon'...
[08:38:08] Finished 'demon' after 1.88 ms
[gulp] [nodemon] v1.2.1
[gulp] [nodemon] to restart at any time, enter `rs`
[gulp] [nodemon] watching: *.*
[gulp] [nodemon] starting `node server/js/server.js`
[08:38:08] Starting 'watch'...
[08:38:09] Finished 'watch' after 31 ms
events.js:72
throw er; // Unhandled 'error' event
^
Error: ENOENT, stat '/Users/jhans/Documents/Code/proj2/client/build/index.html'
Including Gulpfile.
/*jshint globalstrict: true*/
'use strict';
var gulp = require('gulp'),
browserify = require('gulp-browserify'),
clean = require('gulp-clean'),
jshint = require('gulp-jshint'),
stylish = require('jshint-stylish'),
stylus = require('gulp-stylus'),
del = require('del'),
nodemon = require('gulp-nodemon'),
concat = require('gulp-concat');
var paths = {
client: {
scripts: 'client/js/**/*.js',
html: 'client/views/*.html',
index: 'client/*.html',
css: 'client/css/*.styl',
conf: 'client/conf.js'
},
server: {
scripts: 'server/js/**/*.js'
}
};
// Rerun the task when a file changes
gulp.task('watch', function () {
gulp.watch(paths.client.css, ['stylus']);
gulp.watch(paths.client.scripts, ['browserify']);
gulp.watch([paths.client.html, paths.client.index], ['copyClientHTML']);
gulp.watch(paths.server.scripts, ['serverLint']);
});
gulp.task('demon', function () {
nodemon({
script: 'server/js/server.js',
ext: 'js',
env: {
'NODE_ENV': 'development'
}
})
.on('start', ['watch'])
.on('change', ['watch'])
.on('restart', function () {
console.log('restarted!');
});
});
// Default Task
gulp.task('default', ['build', 'demon']);
gulp.task('build', ['stylus', 'copyClientHTML', 'browserify']);
/********** Building CSS *********/
gulp.task('stylus', function () {
del(['client/build/css/*']);
gulp.src(paths.client.css)
.pipe(stylus())
.pipe(concat('all.css'))
.pipe(gulp.dest('client/build/css/'));
});
gulp.task('clientLint', function () {
return gulp.src([paths.client.scripts])
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
gulp.task('serverLint', function () {
return gulp.src([paths.server.scripts])
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
gulp.task('browserify',['clientLint'], function () {
del(['client/build/js/*']);
gulp.src('client/js/app.js')
.pipe(browserify({
insertGlobals: true,
debug: true
}))
.pipe(gulp.dest('client/build/js'));
});
gulp.task('copyClientHTML', function () {
del(['client/build/views/*.*']);
del(['client/build/index.html']);
gulp.src(paths.client.html)
.pipe(gulp.dest('client/build/views'));
gulp.src(paths.client.index)
.pipe(gulp.dest('client/build'));
});
Your problem might come from your copyClientHTML task (and potentially some others).
Indeed, you have to know that the del module does not run synchronously. So it might delete your files after there were created, and can explain the issue you're experiencing.
I may advice you to create a task dedicated to the cleaning of your files that you can put as dependency of some of your tasks; or better a little function where you can pass a parameter to clean specified folders.
This will ensure you that the cleaning is finished before creating the new files.