I have the following gulpfile
gulp.task('browserify', function() {
bundle(false);
});
gulp.task('browserify-watch', function() {
bundle(true);
});
function bundle (performWatch) {
var bify = (performWatch === true
? watchify(browserify(finalBrowserifyOptions))
: browserify(finalBrowserifyOptions));
if (performWatch) {
bify.on('update', function () {
console.log('Updating project files...');
rebundle(bify);
});
}
bify.transform(babelify.configure({
compact: false
}));
function rebundle(bify) {
return bify.bundle()
.on('error', function () {
plugins.util.log('Browserify error');
})
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(plugins.sourcemaps.init({loadMaps: true}))
.pipe(plugins.sourcemaps.write('./'))
.pipe(gulp.dest(paths.build + assets.js));
}
return rebundle(bify);
}
The trouble is that gulp browserify works just fine. However, gulp browserify-watch detects the changes but the output never gets updated.
What am I doing wrong?
I encountered the same watchify failures in file-change detection (both with gulp and grunt). CLI watchify works as expected though. For example:
watchify ./src/app.js -t babelify --outfile ./build/bundle.js -v
Currently I switched to browserify-incremental. The perspective is different in regards to watchify approach. Here's the paragraph from their Github page which encopasses it best:
browserify-incremental can detect changes which occured in between
runs, which means it can be used as part of build systems which are
invoked on demand, without requiring a long lived process. Whereas
watchify is slow for the first run upon each startup,
browserify-incremental is fast every time after the very first.
Here's the "translated" CLI command to make use of browserify-incremental:
browserifyinc ./src/app.js -t babelify --outfile ./build/bundle.js -v
Here's a simple gulpfile.js script for watching and [re]bundling:
var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var babel = require('babelify');
var browserifyInc = require('browserify-incremental');
var bundleApp = function() {
var browserifyObj = browserify('./src/app.js', { debug: false, cache: {}, packageCache: {}, fullPaths: true }).transform(babel);
var bundler = browserifyInc(browserifyObj, {cacheFile: './browserify-cache.json'});
bundler.on('time', function (time) {
console.log('-> Done in ' + time/1000 + ' ms');
});
console.log('-> Bundling...');
bundler.bundle()
.on('error', function(err) { console.error(err); this.emit('end'); })
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./build'));
};
gulp.task('browserify', function () {
gulp.watch('./src/**/*.js', function () {
return bundleApp();
});
});
gulp.task('default', ['browserify']);
Looks like everything was fine my IDE, Webstorm, was caching the file. When I looked at the actual file on the box it was fine.
Related
I have two folders both of which contain some html template files. I need to minify these files to separate folders.
folder structure
|src
|--clientTemplates
|----abc.html
|----xyz.html
|--serverTemplates
|----abc.html
|----xyz.html
required destination folder
|dist
|--client
|----abc.html
|----xyz.html
|--server
|----abc.html
|----xyz.html
following is my gulpfile where I have my tasks defined for the
var gulp = require('gulp');
var htmlmin = require('gulp-htmlmin');
var replace = require('gulp-replace');
var del = require('del');
var minOptions = {
collapseWhitespace: true,
minifyJS: { output: { quote_style: 1 } },
minifyCSS: true
};
gulp.task('clean', function(done) {
del(['dist'], done());
});
gulp.task('minify:serverTemplates', function() {
return gulp
.src('src/serverTemplates/*.html')
.pipe(htmlmin(minOptions))
.pipe(replace('\\', '\\\\'))
.pipe(replace('"', '\\"'))
.pipe(gulp.dest('dist/server'));
});
gulp.task('minify:clientTemplates', function() {
return gulp
.src('src/clientTemplates/*.html')
.pipe(htmlmin(minOptions))
.pipe(gulp.dest('dist/client'));
});
gulp.task(
'default',
gulp.series('clean', 'minify:serverTemplates', 'minify:clientTemplates', function inSeries(done) {
done();
})
);
when I run the gulp command it works fine for the first time, but throws errors on alternate runs.
running gulp command first time
running gulp command second time
can't figure out what exactly is wrong there.
Also is there a way to run the two minification task parallel once the clean task has finished?
thanks for the help.
The callback you pass to del is wrong. Just return the promise:
gulp.task('clean', function() {
return del(['dist']);
});
As for running the minification tasks in parallel, use gulp.parallel:
gulp.task(
'default',
gulp.series(
'clean',
gulp.parallel('minify:serverTemplates', 'minify:clientTemplates')
)
);
Problems I'm facing:
The browser doesn't reflect live changes in .scss or .js
I don't understand whether we have to return the stream from the gulp.task() or not, I visited some websites and watched lectures some of which used return and some didn't.
Cannot understand the flow of execution of gulpfile (which statement runs first, then which and so on)
This is my current code of gulpfile.js.
"use strict";
var gulp = require('gulp');
var sass = require('gulp-sass');
var nodemon = require('gulp-nodemon');
var browserSync = require('browser-sync').create();
var uglify = require('gulp-uglify');
gulp.task('default', ['nodemon'], function(){
gulp.watch("src/sass/*.scss", ['sass']);
gulp.watch("src/js/*.js", ['js']);
gulp.watch("views/*.ejs").on('change',browserSync.reload); //Manual Reloading
})
// Process JS files and return the stream.
gulp.task('js', function () {
return gulp.src('src/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('public/javascripts'));
});
// Compile SASS to CSS.
gulp.task('sass', function(){
// gulp.src('src/sass/*.scss') //without return or with return? why?
return gulp.src('src/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('public/stylesheets'))
.pipe(browserSync.stream());
});
// Setup proxy for local server.
gulp.task('browser-sync', ['js','sass'], function() {
browserSync.init(null, {
proxy: "http://localhost:3000",
port: 7000,
});
});
gulp.task('nodemon', ['browser-sync'], function(cb){
var running = false;
return nodemon({script: 'bin/www'}).on('start', function(){
if(!running)
{
running = true;
cb();
}
});
})
You may look at project structure at https://github.com/DivyanshBatham/GulpWorkflow
Try this:
"use strict";
var gulp = require('gulp');
var sass = require('gulp-sass');
var nodemon = require('gulp-nodemon');
var browserSync = require('browser-sync').create();
var uglify = require('gulp-uglify');
// First, run all your tasks
gulp.task('default', ['nodemon', 'sass', 'js'], function(){
// Then watch for changes
gulp.watch("src/sass/*.scss", ['sass']);
gulp.watch("views/*.ejs").on('change',browserSync.reload); //Manual Reloading
// JS changes need to tell browsersync that they're done
gulp.watch("src/js/*.js", ['js-watch']);
})
// create a task that ensures the `js` task is complete before
// reloading browsers
gulp.task('js-watch', ['js'], function (done) {
browserSync.reload();
done();
});
// Process JS files and return the stream.
gulp.task('js', function () {
return gulp.src('src/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('public/javascripts'));
});
// Compile SASS to CSS.
gulp.task('sass', function(){
return gulp.src('src/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('public/stylesheets'))
.pipe(browserSync.stream());
});
// Setup proxy for local server.
gulp.task('browser-sync', ['js','sass'], function() {
browserSync.init(null, {
proxy: "http://localhost:3000",
port: 7000,
});
});
gulp.task('nodemon', ['browser-sync'], function(cb){
var running = false;
return nodemon({script: 'bin/www'}).on('start', function(){
if(!running)
{
running = true;
cb();
}
});
})
Also, you should consider adding the JS file to your index.ejs
Eg: <script src='/javascripts/main.js'></script>
More help: https://browsersync.io/docs/gulp
I'll answer what I can.
You don't always have to return the stream in a gulp task but you should since you have some tasks, like 'browser-sync' that are dependent on other tasks, ['js','sass'], finishing. The purpose of returning the stream is to signal task completion. It is not the only way to signal task completion but one easy way.
You are already doing this in your ['js','sass'] tasks with the return statements.
Your 'js' task needs a .pipe(browserSync.stream()); statement at the end of it like your 'sass' task. Or try .pipe(browserSync.reload({stream:true})); sometimes that variant works better.
You have both browser-sync and nodemon running - that I believe is unusual and may cause problems - they do much the same thing and do not typically see them running together. I would eliminate nodemon from your file.
Flow of execution:
(a) default calls ['nodemon', 'sass', 'js'] : these run in parallel.
(b) nodemon call 'browser-sync'. 'browserSync' must finish setting up before 'nodemon' gets into its function.
(c) 'browser-sync', ['js','sass'], Here browser-sync is dependent upon 'js' and 'sass' which run in parallel and must finish and signal that they have finished by returning the stream for example before browser-sync continues.
(d) After 'js', 'sass', 'browser-sync' and 'nodemon' have completed, your watch statements are set up and begin to watch.
I am writing a gulp task to browserify, compile my less files into css and to run a gulp-webserver. On Client side I am using React 0.14. The moment any error is found in browserify, my gulp watch crashes. Every time I have to stop the watch task and run it again. How to avoid this? I mean if an error is found and if i fix the error, how can i again run the browserify task without my watch getting crashed. If I get an error in browserify like: the closing JSX tag missing...and Once I fix the error, how to stop my watch from crashing.
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require("babelify");
var source = require('vinyl-source-stream');
var plugins = require('gulp-load-plugins')();
var runSequence = require('run-sequence');
var watchLess = require('gulp-watch-less');
var domain = require("domain");
gulp.task('webserver', function(){
gulp.src('./')
.pipe(plugins.webserver({
fallback : 'index.html',
host : 'localhost',
livereload : {
enable : true
},
open : true
}))
})
gulp.task('browserify', function(){
console.log('Browserifying ...');
return browserify({
entries : ['./js/index.js'],
debug : true
})
.transform('babelify', {presets: ['es2015', 'react']})
.bundle()
.on('error', function(err) {
console.log('Error:', err);
})
.pipe(source('bundle.js'))
.pipe(gulp.dest('./'))
})
gulp.task('build-css', function(){
return gulp.src('./less/**/*.less')
.pipe(plugins.less())
.pipe(gulp.dest('./css'))
})
gulp.task('build', function() {
runSequence(
['build-css'], ['browserify'], ['webserver'], ['watch']
);
});
gulp.task('watch', function(){
gulp.watch('./js/*.js',['browserify'])
gulp.watch('./less/**/*.less',['build-css'])
gulp.watch('./css/**/*.css')
})
add this in your error handling method:
this.emit('end')
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.
});
I've written a nice little build script that runs some pretty standard tasks like...
Cleaning out my deploy/ directory before initially
Building, concatenation, uglifying, and copying files from their dev/ directories to associated deploy/ directories
Watching for changes
etc.
But for better context, I've included just included it below:
var gulp = require('gulp');
var changed = require('gulp-changed');
var newer = require('gulp-newer');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var cssmin = require('gulp-minify-css');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var notify = require('gulp-notify');
var plumber = require('gulp-plumber');
var imagemin = require('gulp-imagemin');
var shopify = require('gulp-shopify-upload');
var watch = require('gulp-watch');
var rename = require('gulp-rename');
var filter = require('gulp-filter');
var flatten = require('gulp-flatten');
var del = require('del');
var argv = require('yargs').argv;
var runsequence = require('run-sequence');
var config = require('./config.json');
var plumberErrorHandler = {
errorHandler: notify.onError({
title: 'Gulp',
message: "Error: <%= error.message %>"
})
};
gulp.task('styles', function() {
return gulp.src(['dev/styles/updates.scss'])
.pipe(plumber(plumberErrorHandler))
.pipe(sourcemaps.init())
.pipe(sass({ errLogToConsole: true }))
.pipe(autoprefixer({ browsers: ['last 2 versions', 'ie >= 10', 'Android >= 4.3'] }))
.pipe(cssmin())
.pipe(sourcemaps.write())
.pipe(rename({ suffix: '.css', extname: '.liquid' }))
.pipe(gulp.dest('deploy/assets'));
});
gulp.task('scripts', function() {
return gulp.src(['dev/scripts/**'])
.pipe(plumber(plumberErrorHandler))
.pipe(sourcemaps.init())
.pipe(concat('main.js'))
.pipe(uglify())
.pipe(sourcemaps.write())
.pipe(rename({ suffix: '.js', extname: '.liquid' }))
.pipe(gulp.dest('deploy/assets'));
});
gulp.task('vendor', function() {
var styles = filter(['styles/**/*.scss']);
var scripts = filter(['scripts/**/*.js']);
return gulp.src(['dev/vendor/**'])
.pipe(plumber(plumberErrorHandler))
.pipe(styles)
.pipe(sass({ errLogToConsole: true }))
.pipe(cssmin())
.pipe(styles.restore())
.pipe(scripts)
.pipe(concat('vendor.js'))
.pipe(uglify())
.pipe(scripts.restore())
.pipe(flatten())
.pipe(gulp.dest('deploy/assets'));
});
gulp.task('copy', function() {
return gulp.src(['dev/liquid/**'], {base: 'dev/liquid'})
.pipe(plumber(plumberErrorHandler))
.pipe(newer('deploy/'))
.pipe(gulp.dest('deploy/'));
});
gulp.task('clean', function(cb) {
del(['deploy/**/*'], cb);
});
gulp.task('imagemin', function() {
return gulp.src(['dev/liquid/assets/*'])
.pipe(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true }))
.pipe(gulp.dest('dev/liquid/assets/'));
});
gulp.task('build', ['clean'], function(cb) {
runsequence(['copy', 'styles', 'scripts', 'vendor'], cb);
});
gulp.task('watch', ['build'], function() {
gulp.watch(['dev/styles/**/*.scss'], ['styles']);
gulp.watch(['dev/scripts/**/*.js'], ['scripts']);
gulp.watch(['dev/vendor/**/*.{js,scss}'], ['vendor']);
gulp.watch(['dev/liquid/**'], ['copy']);
});
gulp.task('upload', ['watch'], function() {
if (!argv.env) {
return false;
} else if (argv.env && config.shopify.hasOwnProperty(argv.env)) {
env = config.shopify[argv.env];
} else {
env = config.shopify.dev;
}
return watch('deploy/{assets|layout|config|snippets|templates|locales}/**')
.pipe(shopify(env.apiKey, env.password, env.url, env.themeId, env.options));
});
gulp.task('default', ['clean', 'build', 'watch', 'upload']);
The problem I've been running into is directly related to the upload task and copy task.
When running gulp --env [environment-name] (e.g. gulp --env staging) or just gulp --env, some of the time when I save a file living in one of the subdirectories of dev/liquid/, the copy task runs as expected, and the singular saved and copied file is then uploaded via. the upload task. However, occasionally I'll save a file and the copy task runs as usual, but then the watch upload freaks out and tries uploading every file inside of deploy/ (which causes an api call limit error, which naturally gives me problems).
I originally had used gulp-changed inside of my copy task, but then noticed that it only will do 1:1 mappings and not directories (not sure how correct I am on this). So I switched to gulp-newer, and things worked for a while, but then things started freaking out again.
I can't figure out what's causing this, I have my suspicions but I can't figure out how to act on them. Any advice, observations, suggestions for improvements, good places for a romantic dinner, reliable pet-sitter, etc. would be greatly appreciated.
tytytytyty!!!
_t
Edit: I've been having a hard time reproducing the freakout (i.e. all files trying to upload at once), and at times running the same gulp --env staging causes a freak out, and other times firing up the same task on the same set of files does nothing. Maybe it could possibly have something to do with gulp-newer and gulp-changed's use of date modified as its comparison??
Double Edit: Maybe it's a race condition cause it works sometimes, and sometimes not? I remember seeing something on the node-glob or minimatch github pages about race conditions....