Instantly share code, notes, and snippets.

What would you like to do?
An over-commented example of a Gulp setup for Express Node apps, with live reload from browser-sync and nodemon as well as a complete build setup using various modules
* Created by alicia.sykes on 17/07/2015.
* To run script run "gulp" in the command line
* To just watch files run "gulp watch"
* To just clean the public directory run "gulp clean"
/* Include the necessary modules */
var gulp = require('gulp');
var gutil = require('gulp-util'); // For logging stats and warnings
var gsize = require('gulp-filesize'); // It's nice to know file size after minifing
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 changed = require('gulp-changed'); // For only updating changed files
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 del = require('del'); // For removing everything from last builds
/* Define constants */
var CONFIG = {
SOURCE_ROOT : "sources", // Folder name for all js and css source
DEST_ROOT : "public", // Folder name for the results root
JS_DIR_NAME : "scripts", // Name of JavaScript directory
CSS_DIR_NAME : "styles", // Name of CSS directory
JS_FILE_NAME : "all.min.js", // Name of output JavaScript file
CSS_FILE_NAME :"all.min.css", // Name of output CSS file
FOOTER_TEXT : "" // Optional footer text for output files
/* Clean the work space */
gulp.task('clean', function (cb) {
], cb);
/* JavaScript Tasks */
gulp.task('scripts', function(){
var jsSrcPath = CONFIG.SOURCE_ROOT + '/'+CONFIG.JS_DIR_NAME+'/**/*';
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(changed(jsResPath)) // Only work with changed files
.pipe(jshint()) // Check js errors or warnings
.pipe(jshint.reporter('jshint-stylish')) // Print js errors or warnings
.pipe(concat(CONFIG.JS_FILE_NAME,{newLine: ';'})) // Concatenate all files together
.pipe(uglify()) // Minify JavaScript
.pipe(footer(CONFIG.FOOTER_TEXT)) // Add footer to script
.pipe(gsize()) // Print the file size, just cos it's cool
.pipe(gulp.dest(jsResPath)) // Save to destination
.on('error', gutil.log); // If error, log to console
/* CSS Tasks */
gulp.task('styles', function(){
var cssSrcPath = CONFIG.SOURCE_ROOT + '/'+CONFIG.CSS_DIR_NAME+'/**/*';
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(changed(cssResPath)) // Only work with changed files
.pipe(cssLint()) // Check CSS for errors or warnings
.pipe(cssLint.reporter()) // And output the results
.pipe(concat(CONFIG.CSS_FILE_NAME)) // Concatenate all files together
.pipe(minCss({compatibility: 'ie8'})) // Minify the CSS
.pipe(gsize()) // Print the file size, just cos it's cool
.pipe(gulp.dest(cssResPath)) // Save to destination
.on('error', gutil.log); // If error, log to console
/* Configure files to watch for changes */
gulp.task('watch', function() {'/**/*.{js,coffee}', ['scripts']);'/**/*.{css,less}', ['styles']);
/* Start Nodemon */
gulp.task('demon', function () {
gulp.start('scripts', 'styles'); // Initially run all tasks
script: './bin/www', // The starting point is app.js
ext: 'js coffee css less html', // File types to watch
ignore: ['public/**/*'], // Ignore the public folder
env: { 'NODE_ENV': 'development'} // Start the server in dev mode
.on('start', function(){ // When the server starts
gulp.start('scripts', 'styles');// Call script and style tasks
.on('change', ['watch']) // On file change call watch method
.on('restart', function () { // When restarted
/* Nodemon task for monitory for changes with live restarting */
gulp.task('nodemon', function (cb) {
var called = false;
return nodemon({
script: './bin/www', // The entry point
watch: ['source/**/*'] // The files to watch for changes in
.on('start', function onStart() {
if (!called) { cb(); } // To stop it constantly restarting
called = true;
.on('restart', function onRestart() {
setTimeout(function reload() { // reload after short pause
stream: false
}, 500);
gulp.task('browser-sync', ['nodemon', 'scripts', 'styles'], function () {
files: [CONFIG.SOURCE_ROOT+'/**/*.*'],
proxy: 'http://localhost:3000',
port: 4000,
browser: ['google chrome'] // Default browser to open
});'/**/*.{js,coffee}', ['scripts']); // Watch and update scripts'/**/*.{css,less}', ['styles']); // Watch and update styles"/**/*").on('change', bSync.reload); // Refresh the browser when any of the sources changes"views/**/*.jade").on('change', bSync.reload); // Refresh browser when jade views change
/* Default Task */
gulp.task('default', ['clean', 'browser-sync']);

This comment has been minimized.


Lissy93 commented Jul 24, 2015

Don't forget to add the devDependencies to your package.json

"devDependencies": {
    "browser-sync": "^2.8.0",
    "del": "^1.2.0",
    "event-stream": "^3.3.1",
    "gulp": "^3.9.0",
    "gulp-changed": "^1.2.1",
    "gulp-coffee": "^2.3.1",
    "gulp-coffeelint": "^0.5.0",
    "gulp-concat": "^2.6.0",
    "gulp-csslint": "^0.1.5",
    "gulp-filesize": "0.0.6",
    "gulp-footer": "^1.0.5",
    "gulp-jshint": "^1.11.2",
    "gulp-less": "^3.0.3",
    "gulp-minify-css": "^1.2.0",
    "gulp-nodemon": "^2.0.3",
    "gulp-uglify": "^1.2.0",
    "gulp-uncss": "^1.0.2",
    "gulp-util": "^3.0.6",
    "jshint-stylish": "^2.0.1"

This comment has been minimized.

NelsonRock commented Oct 1, 2015

Hello and thanks for sharing, i have a problem reloading from task browser-sync'//*.{css,less}', ['styles']);
CONFIG.SOURCE_ROOT = "todos" and my CSS_DIR_NAME = "stylesheets"
my css files under public/stylesheets/ folder
I have uncoment in demo task ignore '/public/
/*/', everything reload in perfect condition even mongodb database, js, hbs but these css files are blocked.

Thanks so much!


This comment has been minimized.

NelsonRock commented Oct 1, 2015

Hello, just if somebody has had the same issue the taks browser-sync
files: ["public/**/.*"],
proxy: 'http://localhost:3000',
port: 4000,
browser: ['google chrome']

that's all!

thanks so much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment