Can I set gulp livereload to run after all files are compiled? - javascript

I've got a gulp set up to work with Stylus, Jade and tiny-lr. My problem is that when I save one jade file, it start's compiling them all, therefore live reloading fires on the first file copied to the destination, before the file I am working on currently is compiled, resulting in me having to refresh manually. I have fixing this issue using "gulp-changed" but I don't seem to be able to configure it or something. Anyone had this problem before? I am posting my Gulp file so you can take a look.
A timeline diagram of the problem can be found here: https://www.dropbox.com/s/3g37oy25s9mq969/jade_compile_frefresh_problem.png?dl=0
Any help is appreciated!
'use strict';
var gulp = require('gulp');
var jade = require('gulp-jade');
var gutil = require('gulp-util');
var stylus = require('gulp-stylus');
var jeet = require('jeet');
var nib = require('nib');
var uglify = require('gulp-uglify');
var lr = require('tiny-lr')();
// var mainBowerFiles = require('main-bower-files');
// Define sources object
var sources = {
jade: "jade/**/*.jade",
partials: "partials/**/*.jade",
stylus: "styl/**/*.styl",
scripts: "js/**/*.js"
};
// Define destinations object
var destinations = {
html: "dist/",
css: "dist/css",
js: "dist/js"
};
// Compile and copy Jade
gulp.task("jade", function(event) {
return gulp.src(sources.jade)
.pipe(jade({
pretty: true
})).pipe(gulp.dest(destinations.html));
});
// Compile and copy Stylus
gulp.task("stylus", function(event) {
return gulp.src(sources.stylus).pipe(stylus({
use: [nib(), jeet()],
import: [
'nib',
'jeet'
],
style: "compressed"
})).pipe(gulp.dest(destinations.css));
});
// Minify and copy all JavaScript
gulp.task('scripts', function() {
gulp.src(sources.scripts)
.pipe(uglify())
.pipe(gulp.dest(destinations.js));
});
// Consolidate Bower Files and copy to /dist/js/
// gulp.task('bower-files', function() {
// return gulp.src(mainBowerFiles(/* options */), {})
// .pipe(gulp.dest(destinations.js));
// });
// Watch for file changes and execute tasks
gulp.task("watch", function() {
gulp.watch(sources.jade, ["jade"]);
gulp.watch(sources.partials, ["jade"]);
gulp.watch(sources.stylus, ["stylus"]);
gulp.watch(sources.scripts, ["scripts"]);
gulp.watch('dist/**/*', refresh);
});
// Live Reload
gulp.task('serve', function () {
var express = require('express');
var app = express();
app.use(require('connect-livereload')());
app.use(express.static(__dirname+'/dist/'));
app.listen(4000, '0.0.0.0');
lr.listen(35729);
});
// Define default task
gulp.task("default", ["jade", "stylus", "scripts", "serve", "watch"]);
// Refresh function
var refresh = function(event) {
var fileName = require('path').relative(__dirname, event.path);
gutil.log.apply(gutil, [gutil.colors.magenta(fileName), gutil.colors.cyan('built')]);
lr.changed({
body: { files: [fileName] }
});
};

I have achieve this by writing a simple javascript function in my gulpfile.js
I did this because when I compile my sass files, livereload will run around 10 times, this method will make it only run once.
My gulpfile.js
gulp.task('watch', function() {
$.livereload.listen();
gulp.watch([
path.join(config.path.app, 'media/js/**/*.js'),
path.join(config.path.app, 'media/css/**/*.css'),
path.join(config.path.app, 'templates/**/*.html')
]).on('change', stackReload);
// a timeout variable
var timer = null;
// actual reload function
function stackReload() {
var reload_args = arguments;
// Stop timeout function to run livereload if this function is ran within the last 250ms
if (timer) clearTimeout(timer);
// Check if any gulp task is still running
if (!gulp.isRunning) {
timer = setTimeout(function() {
$.livereload.changed.apply(null, reload_args);
}, 250);
}
}
});

I have done it. What I had to do is create a new task called "Reload", put dependencies on it and run it after each of the other tasks. Here is the new Gulpfile":
'use strict';
var gulp = require('gulp');
var jade = require('gulp-jade');
var gutil = require('gulp-util');
var stylus = require('gulp-stylus');
var jeet = require('jeet');
var nib = require('nib');
var uglify = require('gulp-uglify');
var livereload = require('gulp-livereload');
var sources = {
jade: "jade/**/*.jade",
partials: "partials/**/*.jade",
stylus: "styl/**/*.styl",
scripts: "js/**/*.js"
};
// Define destinations object
var destinations = {
html: "dist/",
css: "dist/css",
js: "dist/js"
};
// Compile and copy Jade
gulp.task("jade", function(event) {
return gulp.src(sources.jade)
.pipe(jade({pretty: true}))
.pipe(gulp.dest(destinations.html))
});
// Compile and copy Stylus
gulp.task("stylus", function(event) {
return gulp.src(sources.stylus).pipe(stylus({
use: [nib(), jeet()],
import: [
'nib',
'jeet'
],
style: "compressed"
})).pipe(gulp.dest(destinations.css));
});
// Minify and copy all JavaScript
gulp.task('scripts', function() {
gulp.src(sources.scripts)
.pipe(uglify())
.pipe(gulp.dest(destinations.js));
});
// Server
gulp.task('server', function () {
var express = require('express');
var app = express();
app.use(require('connect-livereload')());
app.use(express.static(__dirname+'/dist/'));
app.listen(4000, '0.0.0.0');
});
// Watch sources for change, executa tasks
gulp.task('watch', function() {
livereload.listen();
gulp.watch(sources.jade, ["jade", "refresh"]);
gulp.watch(sources.partials, ["jade", "refresh"]);
gulp.watch(sources.stylus, ["stylus", "refresh"]);
gulp.watch(sources.scripts, ["scripts", "refresh"]);
});
// Refresh task. Depends on Jade task completion
gulp.task("refresh", ["jade"], function(){
livereload.changed();
console.log('LiveReload is triggered');
});
// Define default task
gulp.task("default", ["jade", "stylus", "scripts", "server", "watch"]);

You can use gulp-livereload and write your own callback which send reload event when you want it:
var livereload = require('gulp-livereload'),
path = require('path');
module.exports = function(gulp) {
gulp.task('watch', function() {
livereload.listen();
gulp.watch([
path.resolve(__dirname, '../src/**/*.js'),
path.resolve(__dirname, '../index.html')
]).on('change', function(event) {
livereload.changed();
console.log('File', event.path, 'was', event.type);
console.log('LiveReload is triggered');
});
});
};
UPD: So, for your case you can do this in this way:
1) Install gulp-livereload:
npm install gulp-livereload --save-dev
2) Include gulp-livereload in your gulpfile.js
var livereload = require('gulp-livereload');
3) Replace your old code with watch task, I mean that:
// Watch for file changes and execute tasks
gulp.task("watch", function() {
gulp.watch(sources.jade, ["jade"]);
gulp.watch(sources.partials, ["jade"]);
gulp.watch(sources.stylus, ["stylus"]);
gulp.watch(sources.scripts, ["scripts"]);
gulp.watch('dist/**/*', refresh);
});
And replace it with new code:
gulp.task('watch', function() {
livereload.listen();
gulp.watch([
sources.jade,
sources.partials,
sources.stylus,
sources.scripts,
'dist/**/*'
]).on('change', function(event) {
livereload.changed();
console.log('File', event.path, 'was', event.type);
console.log('LiveReload is triggered');
});
});
4) Of cource check that this configuration fits to your requirements.

I had a similar issue when compiling typescript and then refreshing using livereload. To solve the problem, I created "watch tasks" that run a refresh task once the work is finished.
Below is a minimal code sample taken from your question with the pattern that I've used:
'use strict';
var gulp = require('gulp');
var jade = require('gulp-jade');
var livereload = require('gulp-livereload');
var sources = {
jade: "jade/**/*.jade"
};
var destinations = {
html: "dist/"
};
// Compile and copy Jade
gulp.task("jade", function() {
return gulp.src(sources.jade)
.pipe(jade({pretty: true}))
.pipe(gulp.dest(destinations.html));
});
gulp.task('refresh', function() { return livereload.reload(); });
// execute task, then when finished, refresh
gulp.task("watch-jade", ["jade"], function() { return gulp.start('refresh'); });
gulp.task("watch", function() {
livereload.listen();
gulp.watch(sources.jade, ["watch-jade"]);
});

Related

Gulp watch doesn't "feel" new files

This is my watch.js as written by yeoman gulp-angular generator
'use strict';
var path = require('path');
var gulp = require('gulp');
var conf = require('./conf');
var browserSync = require('browser-sync');
function isOnlyChange(event) {
return event.type === 'changed';
}
gulp.task('watch', ['scripts:watch', 'markups', 'inject'], function () {
gulp.watch([path.join(conf.paths.src, '/*.html'), 'bower.json'], ['inject-reload']);
gulp.watch([
path.join(conf.paths.src, '/app/**/*.css'),
path.join(conf.paths.src, '/app/**/*.scss')
], function(event) {
if(isOnlyChange(event)) {
gulp.start('styles-reload');
} else {
gulp.start('inject-reload');
}
});
gulp.watch(path.join(conf.paths.src, '/app/**/*.jade'), ['markups']);
gulp.watch(path.join(conf.paths.src, '/app/**/*.html'), function(event) {
browserSync.reload(event.path);
});
});
It works fine for already created files, but for some reason gulp.watch doesn't see the new ones (in particular .jade, but maybe also other types), eg.
myApp/src/components/header/headerView.jade
The only solution for me to run task as markup is to stop and restart gulp serve. Then gulp will recognizes changes in my .jade files

gulp will not output js min file

Cant seem to find my problem here. After I run Gulp, the all-css.min.css gets outputted to _build folder but the JS will not go! am I missing something? Cant seem to find what is making this not work.
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var minifyHTML = require('gulp-minify-html');
var sourcemaps = require('gulp-sourcemaps');
var minifyCSS = require('gulp-minify-css');
var inlineCss = require('gulp-inline-css');
var rev = require("gulp-rev");
var del = require('del');
var jsBase = {
src: [
'/Scripts/Core/ko.bindinghandlers-1.0.0.js',
'/Scripts/Twitter/typeahead-0.10.2.js',
'/Scripts/LdCore/mobile-core.js',
'/Scripts/LDCore/Chat.js',
'/Scripts/unsure.js' // These have any unknown lines in them.
]
};
gulp.task('clean', function () {
del.sync(['_build/*'])
});
gulp.task('produce-css', function () {
return gulp.src(cssBase.src)
.pipe(minifyCSS({ keepBreaks: false }))
.pipe(concat('all-css.min.css'))
.pipe(gulp.dest('_build/'))
});
gulp.task('produce-minified-js', function () {
return gulp.src(jsBase.src)
//.pipe(sourcemaps.init())
//.pipe(uglify())
.pipe(concat('all.min.js'))
//.pipe(rev()) // adds random numbers to end.
//.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('_build/'));
});
gulp.task('default', ['clean'], function () {
gulp.start('produce-css', 'produce-minified-js');
});
According to Contra at this post, we shouldn't be using gulp.start.
gulp.start is undocumented on purpose because it can lead to
complicated build files and we don't want people using it
Bad:
gulp.task('default', ['clean'], function () {
gulp.start('produce-css', 'produce-minified-js');
});
Good:
gulp.task('default', ['clean','produce-css','produce-minified-js'], function () {
// Run the dependency chains asynchronously 1st, then do nothing afterwards.
});
It's totally legit to have nothing in the gulp.task, as what it's doing is running the dependency chains asynchronously & then terminating successfully.
You could also do the following:
gulp.task('default', ['clean','produce-css','produce-minified-js'], function (cb) {
// Run a callback to watch the gulp CLI output messages.
cb();
});
Since Gulp creates "Starting default" on the CLI, this would help to display "Finished default" in the CLI after everything else runs.

Gulp watch not called from within Nodemon

So I have my Gulp file as below.
The 'watch' block seems to work absolutely fine, and do what is expected. Nodemon works in the way that it detects file changes and refreshes the server, that works too.
But I can't for the life of me get Nodemon to call the 'watch' method when a file changes.
On line 81, the .on('start' is called succesfully from nodemon, but the code inside the 'watch' method is never executed.
var gulp = require('gulp');
var gutil = require('gulp-util'); // For logging stats and warnings
var jshint = require('gulp-jshint'); // For checking JavaScript for warnings
var concat = require('gulp-concat'); // For joining together multiple files
var uglify = require('gulp-uglify'); // For minimising files
var coffee = require('gulp-coffee'); // For compiling coffee script into js
var cofLint = require('gulp-coffeelint');// For checking coffee script for errors
var less = require('gulp-less'); // For compiling Less into CSS
var cssLint = require('gulp-csslint'); // For checking the awesomeness of css
var minCss = require('gulp-minify-css');// For minifying css
var uncss = require('gulp-uncss'); // For deleting unused CSS rules
var footer = require('gulp-footer'); // For adding footer text into files
var nodemon = require('gulp-nodemon'); // For the super cool instant refreshing server
var bSync = require('browser-sync'); // Syncs the place between multiple browsers for dev
var es = require('event-stream'); // For working with streams rather than temp dirs
var sourcePath = "sources";
var destPath = "public";
var jsFileName = "all.min.js";
var cssFileName = "all.min.css";
var footerText = "";
/* JavaScript Tasks */
gulp.task('scripts', function(){
var jsSrcPath = sourcePath + '/javascript/**/*';
var jsResPath = destPath + '/javascript';
var jsFromCs = gulp.src(jsSrcPath+'.coffee')// Get all coffee script
.pipe(cofLint()) // Check CS for errors or warnings
.pipe(cofLint.reporter()) // Output the error results
.pipe(coffee()); // Convert coffee to vanilla js
var jsFromPlain = gulp.src(jsSrcPath+'.js');// get all vanilla JavaScript
return es.merge(jsFromCs, jsFromPlain) // Both js from cs and vanilla js
.pipe(jshint()) // Check js errors or warnings
.pipe(jshint.reporter('jshint-stylish')) // Print js errors or warnings
.pipe(concat(jsFileName,{newLine: ';'})) // Concatenate all files together
.pipe(uglify()) // Minify JavaScript
.pipe(footer(footerText)) // Add footer to script
.pipe(gulp.dest(jsResPath)); // Save to destination
});
/* CSS Tasks */
gulp.task('styles', function(){
var cssSrcPath = sourcePath + '/styles/**/*';
var cssResPath = destPath + '/stylesheet';
var cssFromLess = gulp.src(cssSrcPath+'.less') // Get all Less code
.pipe(less()); // Convert Less to CSS
var cssFromVanilla = gulp.src(cssSrcPath+'.css');// Get all CSS
return es.merge(cssFromLess, cssFromVanilla) // Combine both CSS
.pipe(cssLint()) // Check CSS for errors or warnings
.pipe(cssLint.reporter()) // And output the results
.pipe(concat(cssFileName)) // Concatenate all files together
.pipe(minCss({compatibility: 'ie8'})) // Minify the CSS
.pipe(gulp.dest(cssResPath)); // Save to destination
});
/* Configure files to watch for changes */
gulp.task('watch', function() {
gulp.watch(sourcePath+'/**/*.{js,coffee}', ['scripts']);
gulp.watch(sourcePath+'/**/*.{css,less}', ['styles']);
});
/* Start Nodemon */
gulp.task('demon', function () {
nodemon({
script: './bin/www',
ext: 'js coffee css less html',
env: { 'NODE_ENV': 'development'}
})
.on('start', ['watch'])//TODO: ERROR: watch is never called, even though start is called
.on('change', ['watch'])
.on('restart', function () {
console.log('restarted!');
});
});
/* Default Task */
gulp.task('default', ['demon']);
Any suggestions why this may be happening?
Is there something wrong with my Gulp file?
(and yes, I know the code is a little over-commented, I work with apprentices and they like English better than code ;)
The problem is that Nodemon and browser-sync both need to be running. This code works:
gulp.task('nodemon', function (cb) {
var called = false;
return nodemon({
script: './bin/www',
watch: ['source/**/*']
})
.on('start', function onStart() {
if (!called) { cb(); }
called = true;
})
.on('restart', function onRestart() {
setTimeout(function reload() {
bSync.reload({
stream: false
});
}, 500);
});
});
gulp.task('browser-sync', ['nodemon', 'scripts', 'styles'], function () {
bSync.init({
files: ['sources/**/*.*'],
proxy: 'http://localhost:3000',
port: 4000,
browser: ['google chrome']
});
gulp.watch(sourcePath+'/**/*.{js,coffee}', ['scripts']);
gulp.watch(sourcePath+'/**/*.{css,less}', ['styles']);
gulp.watch("sources/**/*").on('change', bSync.reload);
gulp.watch("views/**/*.jade").on('change', bSync.reload);
});
/* Default Task */
gulp.task('default', ['clean', 'browser-sync']);

Triggering update from gulpfile when file is updated

In my gulpfile, index.js gets processed, pulls in requirements, and spits out bundle.js. The issue is that I need to trigger an update even when requiredfile.js is updated. Here's my code:
var browserify = require('browserify'),
watchify = require('watchify'),
gulp = require('gulp'),
source = require('vinyl-source-stream'),
sourceFile = './index.js',
destFolder = './',
destFile = 'bundle.js';
gulp.task('browserify', function() {
return browserify(sourceFile, {transform: 'reactify'})
.bundle()
.pipe(source(destFile))
.pipe(gulp.dest(destFolder));
});
gulp.task('watch', function(){
var bundler = browserify(sourceFile, {
debug: true,
cache: {},
packageCache: {},
transform: 'reactify'
});
var watcher = watchify(bundler);
return watcher.on('update', function () { // When any files update
console.log('Updating!');
var updateStart = Date.now();
watcher.bundle()
.pipe(source(destFile))
.pipe(gulp.dest(destFolder));
console.log('Updated!', (Date.now() - updateStart) + 'ms');
})
.bundle() // Create the initial bundle when starting the task
.pipe(source(destFile))
.pipe(gulp.dest(destFolder));
});
gulp.task('default', ['browserify', 'watch']);
How do I add in updating when other files are changed (without causing problems by running requiredfile.js through the same process)?
Figured it out, I added another task to wrap the first, triggered whenever one of the listed files updates.
gulp.task('watchall', function(){
gulp.watch( ['index.js', 'js/*.js', 'js/**/*.js', 'index.html'], ['browserify']);
});
Update: This is a slower update.

How to use the new Browserify API?

I am currently working on a ReactJS project, so I decided to setup a workflow using Gulp to manage the uglification, minification, JSX transformation and so on.
The problem is that the Browserify API is constantly changing (the documentation is not being updated quite often) we can no longer use options inside bundle()
As it is stated by the log error message : "Move all option arguments to the Browserify() constructor"
But not all the options I am using are available, here is my code for now :
var gulp = require('gulp');
var gutil = require('gulp-util');
var streamify = require('gulp-streamify');
var source = require('vinyl-source-stream');
var del = require('del');
prod = gutil.env.prod;
gulp.task('cleanjs', function(cb) {
del(['build/js'], cb);
});
gulp.task('cleancss', function(cb) {
del(['build/css'], cb);
});
gulp.task('sass', ['cleancss'], function() {
var sass = require('gulp-sass');
var concat = require('gulp-concat');
gulp.src(['./src/**/.{css, scss}'])
.pipe(sass())
.pipe(concat('livemap.min.css'))
.pipe(gulp.dest('./build/css'));
});
gulp.task('watch', function() {
var watchify = require('watchify');
var reactify = require('reactify');
var browserify = require('browserify');
var uglify = require('gulp-uglify');
var bundler = watchify(browserify('./src/main.js', {
cache: {},
packageCache: {},
fullPaths: true,
transform: ['reactify'],
debug: true,
}));
function rebundle() {
var t = Date.now();
gutil.log('Starting Watchify rebundle');
return bundler.bundle()
.pipe(source('bundle.js'))
.pipe(prod ? streamify(uglify()) : gutil.noop())
.pipe(gulp.dest('./build/js'))
.on('end', function () {
gutil.log('Finished bundling after:', gutil.colors.magenta(Date.now() - t + ' ms'));
});
}
bundler.on('update', rebundle);
gulp.watch('./src/**/*.{css, scss', ['sass']);
return rebundle();
});
gulp.task('default', ['watch']);
Any help would be very welcome !
Here's how i do it: https://raw.githubusercontent.com/furqanZafar/reactjs-image-upload/master/gulpfile.js
var options = watchify.args;
options.debug = true;
var bundler = browserify(options);
bundler.add("./public/scripts/app.js");
bundler.transform("reactify");
var watcher = watchify(bundler);
.
.
.

Categories