var gulp = require('gulp');
var config = require('./gulp.config')();
var $ = require('gulp-load-plugins')({ lazy: true });
gulp.task('styles', function () {
log('Compiling Less --> CSS');
return gulp
.src(config.less)
.pipe($.plumber())
.pipe($.less())
.pipe($.autoprefixer({ browsers: ['last 3 versions', '> 5%'] }))
.pipe(gulp.dest(config.styles));
});
gulp.task('less-watcher', function () {
gulp.watch([config.less], ['styles']);
});
when I create an error on .less file I receive the error but the watcher hangs and if I fix the error i need to restart the watcher. I thought this was handled by plumber... ?
The problem is in return keyword. remove it to allow plumber works fine!
gulp.task('styles', function () {
log('Compiling Less --> CSS');
gulp.src(config.less)
.pipe($.plumber())
.pipe($.less())
.pipe($.autoprefixer({ browsers: ['last 3 versions', '> 5%'] }))
.pipe(gulp.dest(config.styles)); });
Related
I have a Jekyll site which uses Gulp to compile the Jekyll files amongst other tasks such as compiling my sass, js files and running Browsersync. I'm migrating to Gulp 4.0 so have been updating my gulpfile.js to reflect this...however when I run 'gulp' in command line and update a Jekyll file, the build now loops infinitely. This only happens when I update a Jekyll file or a js file, not when I update a sass file. Here is my code:
var gulp = require('gulp'),
browserSync = require('browser-sync').create(),
sass = require('gulp-sass'),
babel = require('gulp-babel'),
autoprefixer = require('gulp-autoprefixer'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
svgmin = require('gulp-svgmin'),
sourcemaps = require('gulp-sourcemaps'),
cp = require('child_process'),
jekyll = process.platform === 'win32' ? 'jekyll.bat' : 'jekyll';
// =======================================================================
// Browser Sync
// =======================================================================
gulp.task('browser-sync', function(done)
{
browserSync.init({
server: {
baseDir: "_site"
},
port: 3004,
open: false
});
done();
});
gulp.task('browser-sync-reload', function(done)
{
browserSync.reload();
done();
});
// =======================================================================
// SASS
// =======================================================================
var sassOptions = {
includePaths: ['scss'],
errLogToConsole: true,
outputStyle: 'compressed',
//sourceComments: 'map'
};
//Auto prefixer options
var autoPrefixerOptions = {
browsers: ['last 15 versions', '> 1%', 'ie 8', 'ie 7']
};
var styleInput = [
'_sass/**/_*.scss',
'_sass/site.scss'
];
gulp.task('sass-style', function()
{
return gulp.src(styleInput)
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(autoprefixer(autoPrefixerOptions, { cascade: true }))
.pipe(rename('styles.css'))
.pipe(gulp.dest('_site/css'))
.pipe(gulp.dest('css'))
.pipe(browserSync.stream());
});
// =======================================================================
// JS
// =======================================================================
var jsInput = [
'js/libs/**/*.js',
'js/site.js'
];
//Compile js to older browser compatible output
gulp.task('babel-js-min', function() {
return gulp.src(jsInput)
.pipe(sourcemaps.init())
.pipe(babel({
presets: ['#babel/env']
}))
.pipe(concat('site.js'))
.pipe(uglify())
.pipe(rename('scripts.min.js'))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('_site/js/dist'))
.pipe(gulp.dest('js/dist'))
.pipe(browserSync.stream());
});
//Compile js to older browser compatible output
gulp.task('babel-js', function() {
return gulp.src(jsInput)
.pipe(sourcemaps.init())
.pipe(babel({
presets: ['#babel/env']
}))
.pipe(concat('site.js'))
.pipe(rename('scripts.js'))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('_site/js/dist'))
.pipe(gulp.dest('js/dist'))
.pipe(browserSync.stream());
});
// =======================================================================
// SVGs
// =======================================================================
function onError(error)
{
console.log(error);
this.emit('end');
}
var svgInput = [
'_includes/svgs/src/**/*'
];
gulp.task('svgmin', function()
{
return gulp.src(svgInput)
.pipe(svgmin())
.on('error', onError)
.pipe(gulp.dest('./_includes/svgs/dist'));
});
// =======================================================================
// Jekyll
// =======================================================================
var jekyllFiles = [
'_includes/*.html',
'_layouts/*.html',
'**/*.md'
];
gulp.task('jekyll-build', function(done)
{
return cp.spawn("bundle", ["exec", "jekyll", "build"], { stdio: "inherit" }).on('close', done);
});
// =======================================================================
// Watch
// =======================================================================
gulp.task('watch', function()
{
gulp.watch(styleInput, gulp.series('sass-style'));
gulp.watch(jsInput, gulp.series('babel-js-min'));
gulp.watch(jsInput, gulp.series('babel-js'));
gulp.watch(svgInput, gulp.series('svgmin'));
gulp.watch(jekyllFiles, gulp.series('jekyll-build', 'browser-sync-reload'));
});
// =======================================================================
// Define the default task and add the watch task to it
// =======================================================================
gulp.task('default', gulp.parallel('watch', 'browser-sync'));
Any help with this would be appreciated.
I figured this out for anyone that has the same issue...my Jekyll child process was causing the infinite loop (only when editing a Jekyll file). Updating it to the following did the trick:
return cp.spawn(jekyll, ['build', '--incremental', '--drafts'], {stdio: "inherit"}).on('close', done);
Link to Github repo: https://github.com/Greatshock/Netcracker-Study-Course/blob/f9bfb413929feec51064a78abf1450845f867186
I have a file named base.less, where all the styles are #import-ed. When I run the gulpfile (npm run dev), everything is being built, the browser opens the page. However, when I'm changing the content of one of the imported stylesheet, browsersync just writes in the console File event [change] : dist/base.css and nothing happens (even base.css does not actually change). Note that if I change base.less directly by writing some style in it, everything works fine.
Here is my gulpfile.js. Can anyone see the mistake?
'use strict';
const gulp = require('gulp'),
del = require('del'),
autoprefixer = require('gulp-autoprefixer'),
less = require('gulp-less'),
cleanCSS = require('gulp-clean-css'),
gulpIf = require('gulp-if'),
sourceMaps = require('gulp-sourcemaps'),
browserSync = require('browser-sync').create();
const isDevelopment = !process.env.NODE_ENV || process.env.NODE_ENV == 'development';
gulp.task('less', () => {
return gulp.src('src/assets/themes/base/base.less')
.pipe(gulpIf(isDevelopment, sourceMaps.init()))
.pipe(less())
.on('error', onLessError)
.pipe(autoprefixer({
browsers: [
'last 2 versions',
'safari 5',
'ie 10',
'ie 11'
],
cascade: true
}))
.pipe(cleanCSS())
.pipe(gulpIf(isDevelopment, sourceMaps.write()))
.pipe(gulp.dest('prod'));
});
gulp.task('images', () => {
return gulp.src('src/assets/themes/base/images/**/*.*', {base: 'src/assets/themes/base', since: gulp.lastRun('images')})
.pipe(gulp.dest('prod'));
});
gulp.task('index', () => {
return gulp.src('src/index.html', {since: gulp.lastRun('index')})
.pipe(gulp.dest('prod'));
});
gulp.task('clean', () => {
return del('prod');
});
gulp.task('build', gulp.series('clean', gulp.parallel('less', 'images', 'index')));
gulp.task('watch', () => {
gulp.watch('src/assets/themes/base/**/*.less', gulp.series('less'));
gulp.watch('src/assets/themes/base/images/**/*.*', gulp.series('images'));
gulp.watch('src/index.html', gulp.series('index'));
});
gulp.task('serve', function() {
browserSync.init({
server: 'prod'
});
browserSync.watch('prod/**/*.*').on('change', browserSync.reload);
});
gulp.task('dev', gulp.series('build', gulp.parallel('watch', 'serve')));
/***HELPERS FUNCTIONS***/
function onLessError(error) {
console.error(error.message);
this.emit('end');
}
I don't like this hackaround because to me it says one of our plugins isn't working correctly (browser-sync) so we correct it with that broken plugin. I'd maybe try browserify instead.
gulp.task('serve', function() {
browserSync.init({
files: [
{
match: ['src/assets/themes/base/**/*.less'],
fn: function (event, file) {
this.reload()
}
}
],
server: 'prod'
});
browserSync.watch('prod/**/*.*').on('change', browserSync.reload);
});
edit - This could also be a dir issue where the src is different than the watch dir. src/assets/themes/base/**/*.less' should be src/assets/themes/**/*.less' or src/assets/themes/base/*.less' for a distinct folder.
Edit 2- gulp.watch('src/assets/themes/base/*.less', gulp.series('less')); reloads base.less when any other file is changed if added to the gulp command. :D
I've been trying to compile changes to #imports along with those to main SCSS files, and basically have this working.
The issue with my setup: To see changes, I must save files twice (irrespective of whether they're main files or imports). Ideas on this are greatly appreciated.
The directory structure is simply:
--> SCSS
--> SCSS/partials
Here are the relevant parts of my gulpfile:
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var autoprefixer = require('gulp-autoprefixer');
var rename = require('gulp-rename');
var sync = require('browser-sync').create(); // create a browser sync instance.
var sassPaths = [
'bower_components/foundation-sites/scss',
'bower_components/motion-ui/src'
];
var paths = {
'assets': 'assets',
'dev': 'assets/styles/dev'
};
// DEV CSS
gulp.task('dev-styles', function() {
return gulp.src(['scss/**/*.scss', 'scss/*.scss'])
.pipe($.sass({
includePaths: sassPaths,
outputStyles: 'expanded'
})
.on('error', $.sass.logError))
.pipe(autoprefixer({
browsers: ['last 2 versions', 'ie >=9']
}))
.pipe(rename({
suffix: '.dev'
}))
.pipe(gulp.dest('paths.dev'));
});
// DEFAULT WATCH
gulp.task('default', function() {
sync.init({
injectChanges: true,
proxy: 'localhost/basic-modx'
});
gulp.watch([ 'scss/**/*.scss', 'scss/*.scss' ], ['dev-styles']);
gulp.watch([ 'scss/**/*.scss', 'scss/*.scss' ]).on('change', sync.reload);
});
Your watches are set up oddly. I suspect that the second which reloads the browser finishes before the first which actually transpiles the scss, so nothing has changed when the reload occurs. Hence you have to hit save twice.
The better way from browserSync documentation is to have the reload at the end of your 'dev-styles' task like this:
gulp.task('dev-styles', function() {
return gulp.src(['scss/**/*.scss', 'scss/*.scss'])
.pipe($.sass({
includePaths: sassPaths,
outputStyles: 'expanded'
})
.on('error', $.sass.logError))
.pipe(autoprefixer({
browsers: ['last 2 versions', 'ie >=9']
}))
.pipe(rename({
suffix: '.dev'
}))
.pipe(gulp.dest('paths.dev'));
.pipe(sync.stream());
});
and get rid of the second gulp.watch statement.
if I add a new component (_example.scss) to my master.scss and safe it my browser-sync reload automatically and show the style changes from "_example.scss". If I change another thing in this file and safe it, my browser doesnt reload... Any ideas? If I restart gulp, it works perfectly. Is it possible to reinitialize the files that proceed by browser-sync?
Heres my gulpfile.js:
var gulp = require('gulp');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var notify = require('gulp-notify');
var cssmin = require('gulp-cssmin');
var plumber = require('gulp-plumber');
var browserSync = require('browser-sync').create();
var changed = require('gulp-changed');
var autoprefixer = require('gulp-autoprefixer');
var reload = browserSync.reload;
// Compile
gulp.task('sass-master', function () {
gulp.src('./files/layout/scss/master.scss')
.pipe(plumber())
.pipe(sass({}).on('error', function(err) {
return notify().write(err);
}))
.pipe(rename({suffix: '.min'}))
.pipe(cssmin())
.pipe(autoprefixer('last 2 version', '> 1%', 'ie 7', 'ie 8'))
.pipe(gulp.dest('./files/layout/css'))
.pipe(notify('sass-master-task done, ready!'));
});
gulp.task('sass-ieframe', function () {
gulp.src('./files/layout/scss/base/ieframe.scss')
.pipe(plumber())
.pipe(sass({}).on('error', function(err) {
return notify().write(err);
}))
.pipe(rename({suffix: '.min'}))
.pipe(cssmin())
.pipe(gulp.dest('./files/layout/css'))
.pipe(autoprefixer('last 2 version', '> 1%', 'ie 7', 'ie 8'))
.pipe(notify('sass-ieframe-task done, ready!'));
});
gulp.task('sass-fonts', function () {
gulp.src('./files/layout/scss/base/fonts.scss')
.pipe(plumber())
.pipe(sass({}).on('error', function(err) {
return notify().write(err);
}))
.pipe(rename({suffix: '.min'}))
.pipe(cssmin())
.pipe(gulp.dest('./files/layout/css'))
.pipe(autoprefixer('last 2 version', '> 1%', 'ie 7', 'ie 8'))
.pipe(notify('sass-fonts-task done, ready!'));
});
// Serve
gulp.task('browser-sync', function() {
browserSync.init(['./files/layout/css/*.css'], {
proxy: 'dumb-test'
});
});
// Reload Task
gulp.task('bs-reload', function () {
browserSync.reload();
});
// Watch Task
gulp.task('default', ['sass-master', 'sass-fonts', 'sass-ieframe', 'browser-sync'], function () {
gulp.watch(['./files/layout/scss/**/*.scss', './files/layout/scss/master.scss', '!./files/layout/scss/base/ieframe.scss', '!./files/layout/scss/base/fonts.scss'], ['sass-master', 'bs-reload'])
gulp.watch(['./files/layout/scss/base/ieframe.scss'], ['sass-ieframe', 'bs-reload'])
gulp.watch(['./files/layout/scss/base/fonts.scss'], ['sass-fonts', 'bs-reload'])
gulp.watch(['./templates/**/*'], ['bs-reload'])
gulp.watch(['./files/**/*.+(png|jpg|gif|svg)'], ['bs-reload'])
});
I'd say it's a timing issue. Gulp runs tasks in parallel, and your reload tasks should really wait until after the build has finished. e.g. instead of
gulp.watch(['./files/layout/scss/base/ieframe.scss'], ['sass-ieframe', 'bs-reload'])
it should be
gulp.watch(['./files/layout/scss/base/ieframe.scss'], ['sass-ieframe-watch']
with a separate task
gulp.task('sass-ieframe-watch', ['sass-ieframe'], function(done) {
browserSync.reload();
done();
});
Better would be for your sass tasks to reload in the task itself using the streaming option. And the above style used for everything other than sass. This is so that browserSync injects the new css without a full page reload, but the reload is still required for js & html. See https://www.browsersync.io/docs/gulp
I got this Gulp file where I'm running various tasks.
I would like to delete the contents of my build directory before running any other tasks but can't work out how to do this.
I've tried lots of various ways I found when searching for a solution to this but can't get it to work.
Here is my Gulp file:
// List required plugins
var gulp = require('gulp'),
del = require('del'),
uglify = require('gulp-uglify'),
postcss = require('gulp-postcss'),
lost = require('lost'),
nano = require('gulp-cssnano'),
sourcemaps = require('gulp-sourcemaps'),
autoprefixer = require('autoprefixer'),
mqpacker = require('css-mqpacker'),
mixins = require('postcss-mixins'), // Must go before other plugins in the PostCSS task
nested = require('postcss-nested'),
vars = require('postcss-simple-vars'),
partials = require('postcss-import'),
plumber = require('gulp-plumber'),
gutil = require('gulp-util'),
imagemin = require('gulp-imagemin'),
pngquant = require('imagemin-pngquant'),
browserSync = require('browser-sync').create();
// Config - Paths and other config
var src = {
cssDir: 'src/css/**/*.css',
jsDir: 'src/js/**/*.js',
imgDir: 'src/img/*',
svgDir: 'src/img/svg/**/*.svg',
htmlDir: 'src/**/*.html',
srcDir: 'src/',
},
build = {
buildDir: 'build/',
cssDir: 'build/assets/css/',
htmlDir: 'build/**/*.html',
jsDir: 'build/assets/js/',
imgDir: 'build/assets/img/',
},
options = {
autoprefix: { browsers: ['last 2 versions'] },
imagemin: { optimizationLevel: 7, progressive: true, interlaced: true, svgoPlugins: [ {removeViewBox: false}, {cleanupIDs: false} ], use: [pngquant()] },
port: '80',
};
// Error handling function
// Thanks to https://cameronspear.com/blog/how-to-handle-gulp-watch-errors-with-plumber/
var onError = function(err) {
gutil.beep();
console.log(err);
this.emit('end');
}
// Clean task
gulp.task('clean:build', function () {
return del([
build.buildDir,
]);
});
// Copy HTML to Build
gulp.task('html', function () {
return gulp.src(src.htmlDir)
.pipe(plumber({
errorHandler: onError
}))
.pipe(gulp.dest(build.buildDir))
.pipe(browserSync.stream());
});
// BrowserSync Server + watching files for changes
gulp.task('server', function() {
browserSync.init({
server: {
baseDir: build.buildDir
},
port: options.port,
});
});
// PostCSS Task
gulp.task('css', function () {
var processors = [
partials(),
lost(),
autoprefixer({ browsers: ['last 2 version'] }),
mixins(),
nested(),
vars(),
mqpacker(), // Make sure mqpacker is last!
];
return gulp.src(src.cssDir)
.pipe(plumber({
errorHandler: onError
}))
.pipe(sourcemaps.init())
.pipe(postcss(processors))
//.pipe(nano()) - Disable minification during development
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(build.cssDir))
.pipe(browserSync.stream());
});
// JS Task
gulp.task('compressJS', function() {
return gulp.src(src.jsDir)
.pipe(plumber({
errorHandler: onError
}))
.pipe(uglify())
.pipe(gulp.dest(build.jsDir))
.pipe(browserSync.stream());
});
// Image Task
gulp.task('imagemin', function() {
return gulp.src(src.imgDir)
.pipe(plumber({
errorHandler: onError
}))
.pipe(imagemin(
options.imagemin
))
.pipe(gulp.dest(build.imgDir))
.pipe(browserSync.stream());
});
gulp.task('watch', function () {
gulp.watch(src.cssDir, ['css']);
gulp.watch(src.jsDir, ['compressJS']);
gulp.watch(src.htmlDir, ['html']);
gulp.watch(src.imgDir, ['imagemin']);
});
gulp.task('default', ['html', 'imagemin', 'compressJS', 'server', 'watch']);
How should I do to run the task clean:build before any other tasks but only run it once. Or is there a better way of cleaning out files before running a build?
Thanks!!
Have your tasks depend on your clean task:
gulp.task('html', ['clean:build'], function() { ... })
this is how i do it.
var del = require('del') ;
gulp.task('delete-build-folder', function(cb) {
return del([config.buildDir], cb);
});
gulp.task('default', ['delete-build-folder'], function() {
console.log('building.....');
gulp.start('copy-html', 'copy-html-views');
});