Gulp webserver task and watch task not works together - gulp

Here I have a watch task that will create my build directory according to my src. My build directory will contain two main sub directories named debug and release. Watch task will look inside of my src directory(my working directory) and will transfer appropriate format of files inside the src into both release and debug directories. Now I also have a webserver task using gulp-webserver(live reloading) package in order to watching my index.html file inside my debug directory. My problem is that each task works independently, but I don't know how run them simultaneously. Here is what I've tried but it didn't work(just one of them will be start). Let me know if further information is needed.
// watch
gulp.task('watch',()=>{
gulp.watch(pathJS,gulp.series('js','js-min'));
gulp.watch(pathSCSS,gulp.series('sass','sass-min'));
gulp.watch(['src/**/*.*','!'+pathJS,'!'+pathSCSS],gulp.series('cp','cp-min'));
});
// webserver
gulp.task('webserver',()=>{
gulp.src(buildOptions.debugPath)
.pipe(webServer({
fallback: 'index.html',
port:'4000',
livereload:true,
open:true
}))
});
.
.
.
var default_tasks = ['build', 'webserver', 'watch'];
gulp.task('default',gulp.series('clean',...default_tasks));
EDIT:
Here is my full gulpfile.js:
const gulp = require('gulp');
const uglify = require('gulp-uglify-es').default;
const sass = require('gulp-sass');
const del = require('del');
const webServer = require('gulp-webserver');
//-------------------------------------------------------------------------------------------------
const build_tasks=['js','js-min','sass','sass-min','cp','cp-min'];
const buildOptions={
releasePath:'build/release/',
debugPath:'build/debug/',
};
const pathJS = 'src/js/**/*.js'
const pathSCSS = 'src/style/**/*.scss'
//-------------------------------------------------------------------------------------------------
// JavaScript Task
gulp.task('js',()=>{
return gulp.src([pathJS])
.pipe(gulp.dest(buildOptions.debugPath+'/js/'));
});
gulp.task('js-min',()=>{
return gulp.src([pathJS])
.pipe(uglify().on('error',uglify=>console.error(uglify.message)))
.pipe(gulp.dest(buildOptions.releasePath+'/js/'));
})
// sass Task
gulp.task('sass',()=>{
return gulp.src([pathSCSS])
.pipe(sass().on('error',sass.logError))
.pipe(gulp.dest(buildOptions.debugPath+'/style/'));
});
gulp.task('sass-min',()=>{
return gulp.src([pathSCSS])
.pipe(sass({outputStyle: 'compressed'}).on('error',sass.logError))
.pipe(gulp.dest(buildOptions.releasePath+'/style/'))
})
// copy files
gulp.task('cp',()=>{
return gulp.src(['src/**/*.*','!'+pathJS,'!'+pathSCSS])
.pipe(gulp.dest(buildOptions.debugPath));
});
gulp.task('cp-min',()=>{
return gulp.src(['src/**/*.*','!'+pathJS,'!'+pathSCSS])
.pipe(gulp.dest(buildOptions.releasePath));
});
// watch
gulp.task('watch',()=>{
gulp.watch(pathJS,gulp.series('js','js-min'));
gulp.watch(pathSCSS,gulp.series('sass','sass-min'));
gulp.watch(['src/**/*.*','!'+pathJS,'!'+pathSCSS],gulp.series('cp','cp-min'));
});
// webserver
gulp.task('webserver',()=>{
gulp.src(buildOptions.debugPath)
.pipe(webServer({
fallback: 'index.html',
port:'4000',
livereload:true,
open:true
}))
});
//-------------------------------------------------------------------------------------------------
gulp.task('clean',function(){return del(['build']);});
gulp.task('build',gulp.parallel(...build_tasks));
//-------------------------------------------------------------------------------------------------
function build(){
var default_tasks = ['build', 'webserver', 'watch'];
//var default_tasks = ['build', 'watch'];
gulp.task('default',gulp.series('clean',...default_tasks));
}
build();

I solve my problem by using gulp.parallel for both webserver and watch tasks :
// watch
gulp.task('watch',()=>{
gulp.watch(pathJS,gulp.series('js','js-min'));
gulp.watch(pathSCSS,gulp.series('sass','sass-min'));
gulp.watch(['src/**/*.*','!'+pathJS,'!'+pathSCSS],gulp.series('cp','cp-min'));
});
// webserver
gulp.task('webserver',()=>{
gulp.src(buildOptions.debugPath)
.pipe(webServer({
fallback: 'index.html',
port:'4000',
livereload:true,
open:true
}))
});
.
.
.
gulp.task('default',gulp.series('clean','build',gulp.parallel('webserver', 'watch')));//Here is my change!

Related

Gulp - Watch multiple folders and output to relative dist folder

I want to use gulp to compile SASS for my custom Wordpress plugins.
All plugin folder share same folder structure:
wp-content/plugins/pluginname
assets
dist -
src - scss
GULP TASK
gulp.task('plugin-css', () => {
// Main SASS Style Sheet
const pluginSass = gulp.src(`wp-content/plugins/**/assets/src/*.scss`)
.pipe(plumber(plumberErrorHandler))
.pipe(sass());
// Merge the two streams and concatenate their contents into a single file
return merge(pluginSass)
.pipe(autoprefixer())
.pipe(cssmin())
.pipe(gulp.dest(function(file) {
return file.base;
}));
});
Currently my compiled css file is being output into the same folder as the src sass. How can I output my compiled sass into 'dist' folder?
It is not clear to me what you are trying to do with the merges (so NOTE I simplified those out) but here is something that should help you get to putting your result into a dist folder where you want it to be:
var path = require('path');
var rename = require('gulp-rename');
gulp.task('default', function () {
const pluginSass = gulp.src("wp-content/plugins/**/assets/src/*.scss")
.pipe(sass())
// return merge(pluginSass)
.pipe(rename(function (file) {
var temp = path.dirname(file.dirname);
console.log('temp = ' + temp);
file.dirname = path.join(temp, "dist");
console.log("file.dirname = " + file.dirname);
}))
.pipe(cssmin())
// .pipe(autoprefixer())
.pipe(gulp.dest("wp-content/plugins"));
});
gulp-rename is useful for these situations and always seems to be easier to use that gulp.dest(function... path manipulation).
Pass the dist folder to the gulp.dest function.
const path = require('path')
return merge(pluginSass)
.pipe(autoprefixer())
.pipe(cssmin())
.pipe(gulp.dest(function (file) {
return path.join(file.base, './dist') // ← Put your folder path here
}));
See docs here: https://github.com/gulpjs/gulp/blob/master/docs/API.md#gulpdestpath-options

Local preprocessing with Gulp, Stylus, and Browser-sync

I'm trying to setup CSS preprocessing and browser-sync for a client on windows. Prepros seems to be junk, and he can't use codeKit because it's Mac only.
I gave him these resources: https://webdesign.tutsplus.com/tutorials/supercharge-your-local-wordpress-development--cms-28303 and https://browsersync.io/docs/gulp
The preprocessing works great, but the browser has to be manually refreshed to see the CSS changes.
Can you spot what is incorrect in this code? MAMP is also involved... so it could be something else. I'm trying out different configurations to trouble-shoot.
// gulpfile.js
var gulp = require('gulp');
var browserSync = require('browser-sync');
var stylus = require('gulp-stylus');
gulp.task('setup-server', function() {
var files = [
'./style.css',
'./*.php',
];
browserSync.init(files, {
proxy: 'https://website-name.dev',
});
});
gulp.task('compile-stylus', function () {
return gulp.src('stylus/*.styl')
.pipe( stylus({
// options
}))
.pipe( gulp.dest('./') ) // root of theme
.pipe( browserSync.stream() )
;
});
gulp.task('default', ['setup-server', 'compile-stylus'], function() {
gulp.watch('stylus/**/*.styl', ['compile-stylus']);
});
file structure
project-root
gulpfile.js
/stylus
/partials
style.styl
Try these changes:
var browserSync = require("browser-sync").create();
var reload = browserSync.reload;
and the following change at the end of the task:
gulp.task('compile-stylus', function () {
return gulp.src('stylus/*.styl')
.pipe( stylus({
// options
}))
.pipe( gulp.dest('./') ) // root of theme
.pipe( browserSync.reload({stream: true}));
});
And I assume you meant gulpfile.js not gruntfile.js in your folder structure.

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.
});

Gulp - SCSS Lint - Don't compile SCSS if linting fails

Just wondering if someone can help me with my Gulp setup. At the moment I am using gulp-sass and gulp-scss-lint with a watch task. What I want to happen is that when an scss file is saved for the linting task to run completely and if any errors or warnings are thrown up for the scss files not to compile and for watch to continue running.
At the moment I seem to have this working with errors but not with the warnings, which still compile the stylesheets.
/// <binding ProjectOpened='serve' />
// Macmillan Volunteering Village Gulp file.
// This is used to automate the minification
// of stylesheets and javascript files. Run using either
// 'gulp', 'gulp watch' or 'gulp serve' from a command line terminal.
//
// Contents
// --------
// 1. Includes and Requirements
// 2. SASS Automation
// 3. Live Serve
// 4. Watch Tasks
// 5. Build Task
'use strict';
//
// 1. Includes and Requirements
// ----------------------------
// Set the plugin requirements
// for Gulp to function correctly.
var gulp = require('gulp'),
notify = require("gulp-notify"),
sass = require('gulp-sass'),
scssLint = require('gulp-scss-lint'),
gls = require('gulp-live-server'),
// Set the default folder structure
// variables
styleSheets = 'Stylesheets/',
styleSheetsDist = 'Content/css/',
html = 'FrontEnd/';
//
// 2. SASS Automation
// ------------------
// Includes the minification of SASS
// stylesheets. Output will be compressed.
gulp.task('sass', ['scss-lint'], function () {
gulp.src(styleSheets + 'styles.scss')
.pipe(sass({
outputStyle: 'compressed'
}))
.on("error", notify.onError(function (error) {
return error.message;
}))
.pipe(gulp.dest(styleSheetsDist))
.pipe(notify({ message: "Stylesheets Compiled", title: "Stylesheets" }))
});
// SCSS Linting. Ignores the reset file
gulp.task('scss-lint', function () {
gulp.src([styleSheets + '**/*.scss', '!' + styleSheets + '**/_reset.scss'])
.pipe(scssLint({
'endless': true
}))
.on("error", notify.onError(function (error) {
return error.message;
}))
});
//
// 3. Live Serve
// -------------
gulp.task('server', function () {
var server = gls.static('/');
server.start();
// Browser Refresh
gulp.watch([styleSheets + '**/*.scss', html + '**/*.html'], function () {
server.notify.apply(server, arguments);
});
});
// Task to start the server, followed by watch
gulp.task('serve', ['default', 'server', 'watch']);
//
// 4. Watch Tasks
// --------------
gulp.task('watch', function () {
// Stylesheets Watch
gulp.watch(styleSheets + '**/*.scss', ['scss-lint', 'sass']);
});
//
// 5. Build Task
// --------------
gulp.task('default', ['sass']);
Seems that #juanfran has answered this question on GitHub in 2015. I will just repost it here.
1) Using gulp-if you can add any condition you like.
var sass = require('gulp-sass');
var gulpif = require('gulp-if');
var scssLint = require('gulp-scss-lint')
gulp.task('lint', function() {
var condition = function(file) {
return !(file.scssLint.errors || file.scssLint.warnings);
};
return gulp.src('**/*.scss')
.pipe(scssLint())
.pipe(gulpif(condition, sass()));
});
2) Another more specific option is to use Fail reporter that will fail in case of any errors or warnings
gulp.task('scss-lint', function() {
return gulp.src('**/*.scss')
.pipe(scssLint())
.pipe(scssLint.failReporter());
});
gulp.task('sass', ['scss-lint'], function() {
return gulp.src('**/*.scss')
.pipe(scss());
});

How to detect css theme and work only with this theme?

I have a project in which there are about 30 css themes. It means I have the next css files structure:
src/
themes/
default/
a.scss
b.scss
rockStar/
a.scss
b.scss
oneMoreTheme/
a.scss
b.scss
dist/
themes/
default/
styles.css
rockStar/
styles.css
oneMoreTheme/
styles.css
Here is just example of gulpfile:
var gulp = require('gulp'),
glob = require('glob'),
path = require('path'),
_ = require('underscore'),
$ = require('gulp-load-plugins')(),
options = {};
options.themes = [
'default',
'rockStar',
'oneMoreTheme'
];
gulp.task('styles', function () {
_.each(options.themes, function(themeName, themeKey) {
gulp.src('src/themes/' + themeName + '/**/*.scss')
.pipe($.concat('styles.scss'))
.pipe($.sass())
.pipe(gulp.dest('dist/themes/' + themeName + '/'));
});
});
gulp.task('watch', function () {
gulp.watch('src/**/*.*', ['styles']);
});
In my gulp file I have a task "styles", which compiles scss files from each theme and puts compiled files to dist folder.
And I have task "watch" which run "styles" task when any scss file form any source theme changes. It works, but it takes much time because of lots of themes!
How can my task "watch" detect from which theme files changes and run task "styles" only for this changed theme?
That is indeed a tough one, but here is a solution. Please refer to the comments in the code for an explanation.
version 1
var gulp = require('gulp');
var merge = require('merge2');
var $ = require('gulp-load-plugins')();
var path = require('path');
var options = {};
options.themes = [
'default',
'rockStar',
'oneMoreTheme'
];
// we extract the task itself to a new function
// this allows us to reuse it
var styleTask = function(themeName) {
return gulp.src('src/themes/' + themeName + '/**/*.scss')
.pipe($.concat('styles.scss'))
.pipe($.sass())
.pipe(gulp.dest('dist/themes/' + themeName + '/'));
}
// we adapt the style task to use that function
// please note that I switched _.each for merge
// this allows you to work with streams!
gulp.task('styles', function() {
var tasks = themes.map(styleTask);
return merge(tasks);
});
// here we set up a new watcher. Instead of running 'styles'
// we filter the theme directory from the file that has changed
// and run the styleTask function
gulp.task('default', function() {
var watcher = gulp.watch('src/themes/**/*.scss', function(e) {
var theme = path
.relative(__dirname, e.path)
.substr('src/themes/'.length)
.split('/')[0];
console.log('rebuilding ' + theme);
return styleTask('theme');
});
});
version 2
// same as above except the default task. we save the theme
// we want to build in a file
var singleTheme;
// and call the styleTask function should it be set
gulp.task('single-style', function(done) {
if(singleTheme) {
return styleTask(singleTheme);
} else {
done();
}
});
// here we have a watcher that calls single-style, but before calling
// it gets the right themename.
gulp.task('default', function() {
var watcher = gulp.watch('src/themes/**/*.scss', 'single-style');
watcher.on('change', function(e) {
singleTheme = path
.relative(__dirname, e.path)
.substr('src/themes/'.length)
.split('/')[0];
console.log('rebuilding ' + theme);
})
})
I hope this helped.
Update If you want to run more tasks and have a status call on if they ended, please go for version 2. Than you can add all the tasks you want to run in
gulp.task('default', function() {
var watcher = gulp.watch('src/themes/**/*.scss', ['single-style', 'another-task']);
watcher.on('change', function(e) {
singleTheme = path
.relative(__dirname, e.path)
.substr('src/themes/'.length)
.split('/')[0];
console.log('rebuilding ' + theme);
})
})
Instead of gulp.run you can use gulp.start.