Skip to content

Gulp Cheatsheet

Gulp - The Streaming Build System

Gulp is a toolkit for automating painful or time-consuming tasks in your development workflow, so you can stop messing around and build something. It uses Node.js streams, making builds faster by avoiding the need to write temporary files to disk.

Table of Contents

Installation

Global Installation

# Install Gulp CLI globally
npm install -g gulp-cli

# Verify installation
gulp --version

Local Installation

# Initialize npm project
npm init -y

# Install Gulp locally
npm install --save-dev gulp

# Install common plugins
npm install --save-dev gulp-sass gulp-uglify gulp-concat gulp-clean-css

Project Setup

# Create project structure
mkdir my-gulp-project
cd my-gulp-project

# Initialize package.json
npm init -y

# Install Gulp and plugins
npm install --save-dev gulp gulp-sass gulp-autoprefixer gulp-clean-css gulp-uglify gulp-concat gulp-imagemin gulp-htmlmin

# Create gulpfile
touch gulpfile.js

# Create source directories
mkdir -p src/{scss,js,images,html}
mkdir dist

Package.json Scripts

{
  "name": "my-gulp-project",
  "version": "1.0.0",
  "scripts": {
    "build": "gulp build",
    "dev": "gulp dev",
    "watch": "gulp watch",
    "clean": "gulp clean",
    "serve": "gulp serve"
  },
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-sass": "^5.1.0",
    "gulp-autoprefixer": "^8.0.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-uglify": "^3.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-imagemin": "^8.0.0",
    "gulp-htmlmin": "^5.0.1"
  }
}

Getting Started

Basic Gulpfile

// gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const cleanCSS = require('gulp-clean-css');
const uglify = require('gulp-uglify');
const concat = require('gulp-concat');

// Define paths
const paths = {
  styles: {
    src: 'src/scss/**/*.scss',
    dest: 'dist/css/'
  },
  scripts: {
    src: 'src/js/**/*.js',
    dest: 'dist/js/'
  }
};

// Compile Sass
function styles() {
  return gulp.src(paths.styles.src)
    .pipe(sass().on('error', sass.logError))
    .pipe(cleanCSS())
    .pipe(gulp.dest(paths.styles.dest));
}

// Process JavaScript
function scripts() {
  return gulp.src(paths.scripts.src)
    .pipe(concat('main.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.scripts.dest));
}

// Watch files
function watch() {
  gulp.watch(paths.styles.src, styles);
  gulp.watch(paths.scripts.src, scripts);
}

// Export tasks
exports.styles = styles;
exports.scripts = scripts;
exports.watch = watch;
exports.build = gulp.parallel(styles, scripts);
exports.default = gulp.series(exports.build, watch);

Running Tasks

# Run individual tasks
gulp styles
gulp scripts

# Run build task
gulp build

# Run default task (build + watch)
gulp

# Run with specific gulpfile
gulp --gulpfile custom.gulpfile.js

# List available tasks
gulp --tasks

Project Structure

my-gulp-project/
├── src/
   ├── scss/
      ├── main.scss
      ├── _variables.scss
      └── components/
   ├── js/
      ├── main.js
      └── modules/
   ├── images/
   └── html/
├── dist/
   ├── css/
   ├── js/
   ├── images/
   └── index.html
├── gulpfile.js
└── package.json

Core Concepts

Streams and Pipes

// Basic stream example
gulp.src('src/**/*.js')        // Read files
  .pipe(uglify())              // Transform
  .pipe(gulp.dest('dist/'));   // Write files

// Multiple transformations
gulp.src('src/scss/**/*.scss')
  .pipe(sass())                // Compile Sass
  .pipe(autoprefixer())        // Add vendor prefixes
  .pipe(cleanCSS())           // Minify CSS
  .pipe(gulp.dest('dist/css/'));

Glob Patterns

// Glob pattern examples
gulp.src('src/*.js')           // All .js files in src/
gulp.src('src/**/*.js')        // All .js files in src/ and subdirectories
gulp.src('src/js/*.{js,ts}')   // All .js and .ts files in src/js/
gulp.src(['src/**/*.js', '!src/vendor/**']) // Exclude vendor directory

// Multiple sources
gulp.src([
  'src/js/vendor/*.js',
  'src/js/main.js',
  'src/js/modules/*.js'
])

Task Functions

// Named function
function buildCSS() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('dist/css/'));
}

// Arrow function
const buildJS = () => {
  return gulp.src('src/js/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('dist/js/'));
};

// Async function
async function copyFiles() {
  return gulp.src('src/assets/**/*')
    .pipe(gulp.dest('dist/assets/'));
}

// Export tasks
exports.css = buildCSS;
exports.js = buildJS;
exports.copy = copyFiles;

Series and Parallel

const { series, parallel } = require('gulp');

// Run tasks in series (one after another)
const build = series(clean, parallel(styles, scripts), copyAssets);

// Run tasks in parallel (simultaneously)
const dev = parallel(styles, scripts, serve, watch);

// Mixed series and parallel
const deploy = series(
  clean,
  parallel(styles, scripts, images),
  copyFiles,
  uploadToServer
);

exports.build = build;
exports.dev = dev;
exports.deploy = deploy;

Basic Tasks

File Copying

// Simple file copy
function copyHTML() {
  return gulp.src('src/**/*.html')
    .pipe(gulp.dest('dist/'));
}

// Copy with base option
function copyAssets() {
  return gulp.src('src/assets/**/*', { base: 'src' })
    .pipe(gulp.dest('dist/'));
}

// Copy specific files
function copyFonts() {
  return gulp.src([
    'src/fonts/**/*.{woff,woff2,ttf,eot}',
    'node_modules/font-awesome/fonts/**/*'
  ])
  .pipe(gulp.dest('dist/fonts/'));
}

File Cleaning

const del = require('del');

// Clean build directory
function clean() {
  return del(['dist/**', '!dist']);
}

// Clean specific files
function cleanCSS() {
  return del(['dist/css/**/*.css']);
}

// Clean with patterns
function cleanOld() {
  return del([
    'dist/**',
    '!dist/vendor',
    '!dist/vendor/**'
  ]);
}

exports.clean = clean;

File Renaming

const rename = require('gulp-rename');

// Add suffix
function minifyCSS() {
  return gulp.src('src/css/**/*.css')
    .pipe(cleanCSS())
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest('dist/css/'));
}

// Change extension
function compileTypeScript() {
  return gulp.src('src/**/*.ts')
    .pipe(typescript())
    .pipe(rename({ extname: '.js' }))
    .pipe(gulp.dest('dist/js/'));
}

// Custom rename function
function customRename() {
  return gulp.src('src/**/*.scss')
    .pipe(sass())
    .pipe(rename((path) => {
      path.dirname += '/compiled';
      path.basename += '-processed';
    }))
    .pipe(gulp.dest('dist/css/'));
}

File Operations

File Concatenation

const concat = require('gulp-concat');

// Concatenate JavaScript files
function concatJS() {
  return gulp.src([
    'src/js/vendor/*.js',
    'src/js/modules/*.js',
    'src/js/main.js'
  ])
  .pipe(concat('bundle.js'))
  .pipe(gulp.dest('dist/js/'));
}

// Concatenate CSS files
function concatCSS() {
  return gulp.src('src/css/**/*.css')
    .pipe(concat('styles.css'))
    .pipe(gulp.dest('dist/css/'));
}

// Conditional concatenation
function buildVendorJS() {
  return gulp.src([
    'node_modules/jquery/dist/jquery.min.js',
    'node_modules/bootstrap/dist/js/bootstrap.min.js',
    'src/js/vendor/*.js'
  ])
  .pipe(concat('vendor.js'))
  .pipe(gulp.dest('dist/js/'));
}

File Filtering

const gulpif = require('gulp-if');
const filter = require('gulp-filter');

// Conditional processing
function processFiles() {
  const isProduction = process.env.NODE_ENV === 'production';

  return gulp.src('src/js/**/*.js')
    .pipe(gulpif(isProduction, uglify()))
    .pipe(gulp.dest('dist/js/'));
}

// Filter specific files
function processAssets() {
  const jsFilter = filter('**/*.js', { restore: true });
  const cssFilter = filter('**/*.css', { restore: true });

  return gulp.src('src/**/*')
    .pipe(jsFilter)
    .pipe(uglify())
    .pipe(jsFilter.restore)
    .pipe(cssFilter)
    .pipe(cleanCSS())
    .pipe(cssFilter.restore)
    .pipe(gulp.dest('dist/'));
}

File Transformation

const replace = require('gulp-replace');
const template = require('gulp-template');

// String replacement
function updateVersion() {
  return gulp.src('src/**/*.js')
    .pipe(replace('{{VERSION}}', process.env.npm_package_version))
    .pipe(gulp.dest('dist/js/'));
}

// Template processing
function processTemplates() {
  return gulp.src('src/templates/**/*.html')
    .pipe(template({
      title: 'My Website',
      version: '1.0.0',
      timestamp: new Date().toISOString()
    }))
    .pipe(gulp.dest('dist/'));
}

// Multiple replacements
function processConfig() {
  return gulp.src('src/config.js')
    .pipe(replace('{{API_URL}}', process.env.API_URL || 'http://localhost:3000'))
    .pipe(replace('{{DEBUG}}', process.env.NODE_ENV === 'development'))
    .pipe(gulp.dest('dist/js/'));
}

CSS Processing

Sass Compilation

const sass = require('gulp-sass')(require('sass'));
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
const sourcemaps = require('gulp-sourcemaps');

// Basic Sass compilation
function compileSass() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('dist/css/'));
}

// Advanced Sass processing
function processCSS() {
  return gulp.src('src/scss/main.scss')
    .pipe(sourcemaps.init())
    .pipe(sass({
      outputStyle: 'expanded',
      includePaths: ['node_modules']
    }).on('error', sass.logError))
    .pipe(autoprefixer({
      cascade: false
    }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('dist/css/'))
    .pipe(cleanCSS())
    .pipe(rename({ suffix: '.min' }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('dist/css/'));
}

// Production CSS build
function buildProductionCSS() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(sass({
      outputStyle: 'compressed',
      includePaths: ['node_modules/bootstrap/scss']
    }))
    .pipe(autoprefixer({
      browsers: ['last 2 versions', '> 1%'],
      cascade: false
    }))
    .pipe(cleanCSS({
      level: 2
    }))
    .pipe(gulp.dest('dist/css/'));
}

PostCSS Processing

const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const tailwindcss = require('tailwindcss');

// PostCSS with plugins
function processPostCSS() {
  const plugins = [
    tailwindcss(),
    autoprefixer(),
    cssnano()
  ];

  return gulp.src('src/css/**/*.css')
    .pipe(postcss(plugins))
    .pipe(gulp.dest('dist/css/'));
}

// Tailwind CSS processing
function buildTailwind() {
  return gulp.src('src/css/tailwind.css')
    .pipe(postcss([
      tailwindcss('./tailwind.config.js'),
      autoprefixer(),
      ...(process.env.NODE_ENV === 'production' ? [cssnano()] : [])
    ]))
    .pipe(gulp.dest('dist/css/'));
}

CSS Optimization

const purgecss = require('gulp-purgecss');
const critical = require('critical');

// Remove unused CSS
function purgeCSS() {
  return gulp.src('dist/css/**/*.css')
    .pipe(purgecss({
      content: ['dist/**/*.html', 'dist/**/*.js'],
      safelist: ['active', 'show', /^carousel-/]
    }))
    .pipe(gulp.dest('dist/css/'));
}

// Extract critical CSS
function extractCritical() {
  return critical.generate({
    base: 'dist/',
    src: 'index.html',
    dest: 'css/critical.css',
    inline: true,
    width: 1300,
    height: 900
  });
}

// CSS linting
const stylelint = require('gulp-stylelint');

function lintCSS() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(stylelint({
      reporters: [
        { formatter: 'string', console: true }
      ]
    }));
}

JavaScript Processing

Basic JavaScript Processing

const uglify = require('gulp-uglify');
const babel = require('gulp-babel');
const concat = require('gulp-concat');

// Basic JavaScript minification
function minifyJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('dist/js/'));
}

// Babel transpilation
function transpileJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(babel({
      presets: ['@babel/env']
    }))
    .pipe(gulp.dest('dist/js/'));
}

// Complete JavaScript pipeline
function processJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(sourcemaps.init())
    .pipe(babel({
      presets: ['@babel/env']
    }))
    .pipe(concat('bundle.js'))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('dist/js/'))
    .pipe(uglify())
    .pipe(rename({ suffix: '.min' }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('dist/js/'));
}

TypeScript Processing

const typescript = require('gulp-typescript');

// TypeScript compilation
function compileTypeScript() {
  const tsProject = typescript.createProject('tsconfig.json');

  return tsProject.src()
    .pipe(tsProject())
    .js
    .pipe(gulp.dest('dist/js/'));
}

// TypeScript with source maps
function buildTypeScript() {
  const tsProject = typescript.createProject('tsconfig.json');

  return gulp.src('src/ts/**/*.ts')
    .pipe(sourcemaps.init())
    .pipe(tsProject())
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('dist/js/'));
}

JavaScript Bundling

const browserify = require('browserify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

// Browserify bundling
function bundleJS() {
  return browserify({
    entries: 'src/js/main.js',
    debug: true
  })
  .bundle()
  .pipe(source('bundle.js'))
  .pipe(buffer())
  .pipe(sourcemaps.init({ loadMaps: true }))
  .pipe(uglify())
  .pipe(sourcemaps.write('./'))
  .pipe(gulp.dest('dist/js/'));
}

// Webpack integration
const webpack = require('webpack-stream');

function webpackBundle() {
  return gulp.src('src/js/main.js')
    .pipe(webpack({
      mode: 'production',
      output: {
        filename: 'bundle.js'
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      }
    }))
    .pipe(gulp.dest('dist/js/'));
}

JavaScript Linting

const eslint = require('gulp-eslint');
const jshint = require('gulp-jshint');

// ESLint
function lintJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
}

// JSHint
function hintJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'))
    .pipe(jshint.reporter('fail'));
}

// Combined linting
function checkJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
}

Image Optimization

Basic Image Processing

const imagemin = require('gulp-imagemin');
const webp = require('gulp-webp');
const responsive = require('gulp-responsive');

// Basic image optimization
function optimizeImages() {
  return gulp.src('src/images/**/*')
    .pipe(imagemin([
      imagemin.gifsicle({ interlaced: true }),
      imagemin.mozjpeg({ quality: 75, progressive: true }),
      imagemin.optipng({ optimizationLevel: 5 }),
      imagemin.svgo({
        plugins: [
          { removeViewBox: true },
          { cleanupIDs: false }
        ]
      })
    ]))
    .pipe(gulp.dest('dist/images/'));
}

// WebP conversion
function generateWebP() {
  return gulp.src('src/images/**/*.{jpg,jpeg,png}')
    .pipe(webp())
    .pipe(gulp.dest('dist/images/webp/'));
}

// Responsive images
function createResponsiveImages() {
  return gulp.src('src/images/**/*.{jpg,jpeg,png}')
    .pipe(responsive({
      '**/*': [
        {
          width: 320,
          rename: { suffix: '-small' }
        },
        {
          width: 640,
          rename: { suffix: '-medium' }
        },
        {
          width: 1024,
          rename: { suffix: '-large' }
        },
        {
          width: 1920,
          rename: { suffix: '-xlarge' }
        }
      ]
    }))
    .pipe(gulp.dest('dist/images/responsive/'));
}

Advanced Image Processing

const sharp = require('gulp-sharp-responsive');
const sprite = require('gulp.spritesmith');

// Sharp image processing
function processWithSharp() {
  return gulp.src('src/images/**/*.{jpg,jpeg,png}')
    .pipe(sharp({
      formats: [
        { format: 'jpeg', options: { quality: 80 } },
        { format: 'webp', options: { quality: 80 } }
      ]
    }))
    .pipe(gulp.dest('dist/images/'));
}

// CSS Sprites
function createSprites() {
  const spriteData = gulp.src('src/images/icons/*.png')
    .pipe(sprite({
      imgName: 'sprite.png',
      cssName: 'sprite.css',
      imgPath: '../images/sprite.png'
    }));

  spriteData.img.pipe(gulp.dest('dist/images/'));
  spriteData.css.pipe(gulp.dest('dist/css/'));

  return spriteData;
}

// SVG sprites
const svgSprite = require('gulp-svg-sprite');

function createSVGSprites() {
  return gulp.src('src/images/icons/*.svg')
    .pipe(svgSprite({
      mode: {
        symbol: {
          dest: '.',
          sprite: 'sprite.svg'
        }
      }
    }))
    .pipe(gulp.dest('dist/images/'));
}

HTML Processing

HTML Minification

const htmlmin = require('gulp-htmlmin');
const fileinclude = require('gulp-file-include');
const replace = require('gulp-replace');

// Basic HTML minification
function minifyHTML() {
  return gulp.src('src/**/*.html')
    .pipe(htmlmin({
      collapseWhitespace: true,
      removeComments: true,
      removeRedundantAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      useShortDoctype: true
    }))
    .pipe(gulp.dest('dist/'));
}

// HTML includes
function processHTML() {
  return gulp.src('src/pages/*.html')
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest('dist/'));
}

// HTML templating
function buildHTML() {
  return gulp.src('src/templates/*.html')
    .pipe(replace('{{TITLE}}', 'My Website'))
    .pipe(replace('{{VERSION}}', process.env.npm_package_version))
    .pipe(htmlmin({
      collapseWhitespace: true,
      removeComments: true
    }))
    .pipe(gulp.dest('dist/'));
}

HTML Validation and Processing

const htmlhint = require('gulp-htmlhint');
const w3cjs = require('gulp-w3cjs');
const inject = require('gulp-inject');

// HTML validation
function validateHTML() {
  return gulp.src('dist/**/*.html')
    .pipe(htmlhint())
    .pipe(htmlhint.reporter())
    .pipe(w3cjs())
    .pipe(w3cjs.reporter());
}

// Asset injection
function injectAssets() {
  const target = gulp.src('src/index.html');
  const sources = gulp.src(['dist/js/**/*.js', 'dist/css/**/*.css'], { read: false });

  return target
    .pipe(inject(sources, {
      relative: true,
      transform: function (filepath) {
        if (filepath.slice(-3) === '.js') {
          return '<script src="' + filepath + '"></script>';
        }
        return '<link rel="stylesheet" href="' + filepath + '">';
      }
    }))
    .pipe(gulp.dest('dist/'));
}

Development Server

Basic Server Setup

const browserSync = require('browser-sync').create();
const connect = require('gulp-connect');

// Browser Sync server
function serve() {
  browserSync.init({
    server: {
      baseDir: 'dist'
    },
    port: 3000,
    open: true
  });
}

// Connect server
function connectServer() {
  connect.server({
    root: 'dist',
    livereload: true,
    port: 8080
  });
}

// Reload browser
function reload(done) {
  browserSync.reload();
  done();
}

Advanced Server Configuration

// Advanced Browser Sync setup
function advancedServe() {
  browserSync.init({
    server: {
      baseDir: 'dist',
      middleware: [
        // Custom middleware
        function(req, res, next) {
          console.log('Request:', req.url);
          next();
        }
      ]
    },
    port: 3000,
    ui: {
      port: 3001
    },
    files: [
      'dist/**/*.html',
      'dist/**/*.css',
      'dist/**/*.js'
    ],
    reloadDelay: 1000,
    notify: false,
    ghostMode: {
      clicks: true,
      forms: true,
      scroll: true
    }
  });
}

// Proxy server
function proxyServe() {
  browserSync.init({
    proxy: 'localhost:8080',
    port: 3000,
    files: ['dist/**/*'],
    reloadDelay: 1000
  });
}

Live Reload

// Live reload with gulp-connect
function liveReload() {
  return gulp.src('dist/**/*.html')
    .pipe(connect.reload());
}

// Watch with live reload
function watchWithReload() {
  gulp.watch('src/scss/**/*.scss', gulp.series(styles, reload));
  gulp.watch('src/js/**/*.js', gulp.series(scripts, reload));
  gulp.watch('src/**/*.html', gulp.series(copyHTML, reload));
}

// Complete development server
function dev() {
  serve();
  watchWithReload();
}

exports.serve = serve;
exports.dev = dev;

Watch Tasks

Basic Watch Setup

// Basic watch
function watch() {
  gulp.watch('src/scss/**/*.scss', styles);
  gulp.watch('src/js/**/*.js', scripts);
  gulp.watch('src/**/*.html', copyHTML);
  gulp.watch('src/images/**/*', images);
}

// Watch with options
function watchAdvanced() {
  gulp.watch('src/scss/**/*.scss', {
    events: 'all',
    delay: 500
  }, styles);

  gulp.watch('src/js/**/*.js', {
    ignoreInitial: false
  }, scripts);
}

Advanced Watch Patterns

const chokidar = require('chokidar');

// Custom watcher
function customWatch() {
  // Watch SCSS files
  const scssWatcher = chokidar.watch('src/scss/**/*.scss');
  scssWatcher.on('change', () => {
    console.log('SCSS file changed');
    styles();
  });

  // Watch JS files
  const jsWatcher = chokidar.watch('src/js/**/*.js');
  jsWatcher.on('add', () => {
    console.log('JS file added');
    scripts();
  });
  jsWatcher.on('unlink', () => {
    console.log('JS file removed');
    scripts();
  });
}

// Conditional watching
function conditionalWatch() {
  if (process.env.NODE_ENV === 'development') {
    gulp.watch('src/scss/**/*.scss', gulp.series(styles, reload));
    gulp.watch('src/js/**/*.js', gulp.series(lintJS, scripts, reload));
  } else {
    gulp.watch('src/scss/**/*.scss', styles);
    gulp.watch('src/js/**/*.js', scripts);
  }
}

Watch with Error Handling

const plumber = require('gulp-plumber');
const notify = require('gulp-notify');

// Error handling in watch
function watchWithErrors() {
  gulp.watch('src/scss/**/*.scss', () => {
    return gulp.src('src/scss/**/*.scss')
      .pipe(plumber({
        errorHandler: notify.onError({
          title: 'Sass Error',
          message: '<%= error.message %>'
        })
      }))
      .pipe(sass())
      .pipe(gulp.dest('dist/css/'))
      .pipe(browserSync.stream());
  });
}

// Graceful error handling
function gracefulWatch() {
  gulp.watch('src/js/**/*.js', () => {
    return gulp.src('src/js/**/*.js')
      .pipe(plumber())
      .pipe(babel())
      .on('error', function(err) {
        console.error('Error:', err.message);
        this.emit('end');
      })
      .pipe(uglify())
      .pipe(gulp.dest('dist/js/'));
  });
}

Build Pipeline

Development Build

// Development build pipeline
const developmentBuild = gulp.series(
  clean,
  gulp.parallel(
    copyHTML,
    gulp.series(lintCSS, styles),
    gulp.series(lintJS, scripts),
    copyAssets,
    optimizeImages
  )
);

// Development with watch
const dev = gulp.series(
  developmentBuild,
  gulp.parallel(serve, watch)
);

exports.dev = dev;

Production Build

// Production build pipeline
const productionBuild = gulp.series(
  clean,
  gulp.parallel(
    minifyHTML,
    buildProductionCSS,
    buildProductionJS,
    optimizeImages,
    copyAssets
  ),
  injectAssets,
  generateSitemap
);

// Production JavaScript build
function buildProductionJS() {
  return gulp.src('src/js/**/*.js')
    .pipe(babel({
      presets: ['@babel/env']
    }))
    .pipe(concat('bundle.js'))
    .pipe(uglify())
    .pipe(rev())
    .pipe(gulp.dest('dist/js/'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('dist/'));
}

exports.build = productionBuild;

Multi-Environment Builds

const gulpif = require('gulp-if');

// Environment-aware build
function buildForEnvironment() {
  const isProduction = process.env.NODE_ENV === 'production';
  const isDevelopment = process.env.NODE_ENV === 'development';

  return gulp.src('src/js/**/*.js')
    .pipe(gulpif(isDevelopment, sourcemaps.init()))
    .pipe(babel())
    .pipe(gulpif(isProduction, uglify()))
    .pipe(gulpif(isDevelopment, sourcemaps.write('.')))
    .pipe(gulp.dest('dist/js/'));
}

// Multiple environment configs
const environments = {
  development: {
    sourcemaps: true,
    minify: false,
    baseUrl: 'http://localhost:3000'
  },
  staging: {
    sourcemaps: true,
    minify: true,
    baseUrl: 'https://staging.example.com'
  },
  production: {
    sourcemaps: false,
    minify: true,
    baseUrl: 'https://example.com'
  }
};

function buildWithConfig() {
  const env = process.env.NODE_ENV || 'development';
  const config = environments[env];

  return gulp.src('src/**/*.js')
    .pipe(gulpif(config.sourcemaps, sourcemaps.init()))
    .pipe(replace('{{BASE_URL}}', config.baseUrl))
    .pipe(gulpif(config.minify, uglify()))
    .pipe(gulpif(config.sourcemaps, sourcemaps.write('.')))
    .pipe(gulp.dest('dist/js/'));
}

Plugin Ecosystem

Essential Plugins

# Core plugins
npm install --save-dev gulp-sass gulp-autoprefixer gulp-clean-css
npm install --save-dev gulp-uglify gulp-concat gulp-babel
npm install --save-dev gulp-imagemin gulp-htmlmin

# Utility plugins
npm install --save-dev gulp-sourcemaps gulp-rename gulp-if
npm install --save-dev gulp-plumber gulp-notify gulp-filter

# Development plugins
npm install --save-dev browser-sync gulp-connect
npm install --save-dev gulp-eslint gulp-stylelint

# Advanced plugins
npm install --save-dev gulp-rev gulp-inject gulp-replace
npm install --save-dev gulp-zip gulp-ftp gulp-s3-upload

File Processing Plugins

// File manipulation
const rev = require('gulp-rev');
const revReplace = require('gulp-rev-replace');
const size = require('gulp-size');

// Asset revisioning
function revisionAssets() {
  return gulp.src(['dist/**/*.css', 'dist/**/*.js'])
    .pipe(rev())
    .pipe(gulp.dest('dist/'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('dist/'));
}

// Replace revisioned assets
function replaceRevisionedAssets() {
  const manifest = gulp.src('dist/rev-manifest.json');

  return gulp.src('dist/**/*.html')
    .pipe(revReplace({ manifest: manifest }))
    .pipe(gulp.dest('dist/'));
}

// File size reporting
function reportSizes() {
  return gulp.src('dist/**/*')
    .pipe(size({
      showFiles: true,
      gzip: true
    }));
}

Testing Plugins

const mocha = require('gulp-mocha');
const karma = require('karma').Server;
const jest = require('gulp-jest');

// Mocha tests
function runMochaTests() {
  return gulp.src('test/**/*.js', { read: false })
    .pipe(mocha({
      reporter: 'spec'
    }));
}

// Karma tests
function runKarmaTests(done) {
  new karma({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  }, done).start();
}

// Jest tests
function runJestTests() {
  return gulp.src('.')
    .pipe(jest({
      preprocessorIgnorePatterns: [
        '<rootDir>/dist/', '<rootDir>/node_modules/'
      ],
      automock: false
    }));
}

Deployment Plugins

const ftp = require('vinyl-ftp');
const s3 = require('gulp-s3-upload')();
const ghPages = require('gulp-gh-pages');

// FTP deployment
function deployFTP() {
  const conn = ftp.create({
    host: 'ftp.example.com',
    user: process.env.FTP_USER,
    password: process.env.FTP_PASSWORD,
    parallel: 10
  });

  return gulp.src('dist/**/*', { base: 'dist', buffer: false })
    .pipe(conn.newer('/public_html'))
    .pipe(conn.dest('/public_html'));
}

// S3 deployment
function deployS3() {
  return gulp.src('dist/**/*')
    .pipe(s3({
      Bucket: 'my-bucket',
      ACL: 'public-read'
    }));
}

// GitHub Pages deployment
function deployGitHub() {
  return gulp.src('dist/**/*')
    .pipe(ghPages());
}

Advanced Patterns

Custom Plugins

const through = require('through2');
const PluginError = require('plugin-error');

// Simple custom plugin
function customPlugin(options) {
  options = options || {};

  return through.obj(function(file, encoding, callback) {
    if (file.isNull()) {
      return callback(null, file);
    }

    if (file.isStream()) {
      return callback(new PluginError('custom-plugin', 'Streaming not supported'));
    }

    try {
      // Process file content
      const content = file.contents.toString();
      const processed = content.replace(/foo/g, 'bar');
      file.contents = Buffer.from(processed);

      this.push(file);
      callback();
    } catch (err) {
      callback(new PluginError('custom-plugin', err));
    }
  });
}

// Usage
function useCustomPlugin() {
  return gulp.src('src/**/*.js')
    .pipe(customPlugin({ option: 'value' }))
    .pipe(gulp.dest('dist/'));
}

Stream Processing

const map = require('map-stream');
const transform = require('stream-transform');

// Map stream processing
function processWithMap() {
  return gulp.src('src/**/*.js')
    .pipe(map((file, callback) => {
      // Process each file
      const content = file.contents.toString();
      const processed = content.toUpperCase();
      file.contents = Buffer.from(processed);
      callback(null, file);
    }))
    .pipe(gulp.dest('dist/'));
}

// Transform stream
function processWithTransform() {
  return gulp.src('src/**/*.json')
    .pipe(transform((file, encoding, callback) => {
      try {
        const data = JSON.parse(file.contents.toString());
        data.processed = true;
        data.timestamp = new Date().toISOString();
        file.contents = Buffer.from(JSON.stringify(data, null, 2));
        callback(null, file);
      } catch (err) {
        callback(err);
      }
    }))
    .pipe(gulp.dest('dist/'));
}

Conditional Processing

const yargs = require('yargs');
const gulpif = require('gulp-if');

// Command line arguments
const argv = yargs.argv;

function conditionalBuild() {
  return gulp.src('src/**/*.js')
    .pipe(gulpif(argv.lint, eslint()))
    .pipe(gulpif(argv.babel, babel()))
    .pipe(gulpif(argv.minify, uglify()))
    .pipe(gulp.dest('dist/'));
}

// Environment-based conditions
function environmentalBuild() {
  const isProduction = process.env.NODE_ENV === 'production';
  const isDevelopment = !isProduction;

  return gulp.src('src/**/*.js')
    .pipe(gulpif(isDevelopment, sourcemaps.init()))
    .pipe(babel())
    .pipe(gulpif(isProduction, uglify()))
    .pipe(gulpif(isDevelopment, sourcemaps.write('.')))
    .pipe(gulp.dest('dist/'));
}

// File-based conditions
function fileBasedProcessing() {
  return gulp.src('src/**/*')
    .pipe(gulpif('*.js', uglify()))
    .pipe(gulpif('*.css', cleanCSS()))
    .pipe(gulpif('*.html', htmlmin()))
    .pipe(gulp.dest('dist/'));
}

Performance Optimization

Parallel Processing

// Parallel task execution
const parallelBuild = gulp.parallel(
  styles,
  scripts,
  images,
  copyAssets
);

// Mixed series and parallel
const optimizedBuild = gulp.series(
  clean,
  gulp.parallel(
    gulp.series(lintCSS, styles),
    gulp.series(lintJS, scripts),
    images
  ),
  injectAssets
);

exports.build = optimizedBuild;

Incremental Builds

const changed = require('gulp-changed');
const newer = require('gulp-newer');

// Process only changed files
function incrementalStyles() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(changed('dist/css/', { extension: '.css' }))
    .pipe(sass())
    .pipe(gulp.dest('dist/css/'));
}

// Process only newer files
function incrementalImages() {
  return gulp.src('src/images/**/*')
    .pipe(newer('dist/images/'))
    .pipe(imagemin())
    .pipe(gulp.dest('dist/images/'));
}

// Cache-based processing
const cache = require('gulp-cache');

function cachedImages() {
  return gulp.src('src/images/**/*')
    .pipe(cache(imagemin()))
    .pipe(gulp.dest('dist/images/'));
}

Memory Optimization

const remember = require('gulp-remember');
const cached = require('gulp-cached');

// Cached processing with remember
function optimizedScripts() {
  return gulp.src('src/js/**/*.js')
    .pipe(cached('scripts'))
    .pipe(eslint())
    .pipe(remember('scripts'))
    .pipe(concat('bundle.js'))
    .pipe(gulp.dest('dist/js/'));
}

// Clear cache when needed
function clearCache() {
  return cache.clearAll();
}

// Memory-efficient streaming
function streamEfficient() {
  return gulp.src('src/**/*.js', { buffer: false })
    .pipe(someTransform())
    .pipe(gulp.dest('dist/'));
}

Error Handling

Basic Error Handling

const plumber = require('gulp-plumber');
const notify = require('gulp-notify');

// Plumber for error handling
function errorHandledStyles() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(plumber({
      errorHandler: function(err) {
        console.error('Error:', err.message);
        this.emit('end');
      }
    }))
    .pipe(sass())
    .pipe(gulp.dest('dist/css/'));
}

// Notify on errors
function notifyOnError() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(plumber({
      errorHandler: notify.onError({
        title: 'Sass Error',
        message: '<%= error.message %>'
      })
    }))
    .pipe(sass())
    .pipe(gulp.dest('dist/css/'));
}

Advanced Error Handling

// Custom error handler
function createErrorHandler(taskName) {
  return function(err) {
    console.error(`Error in ${taskName}:`, err.message);
    if (err.stack) {
      console.error(err.stack);
    }
    this.emit('end');
  };
}

// Error handling with logging
const log = require('fancy-log');
const colors = require('ansi-colors');

function advancedErrorHandling() {
  return gulp.src('src/js/**/*.js')
    .pipe(plumber({
      errorHandler: function(err) {
        log.error(colors.red('JavaScript Error:'));
        log.error(colors.red(err.message));
        if (err.fileName) {
          log.error(colors.yellow('File:'), err.fileName);
        }
        if (err.lineNumber) {
          log.error(colors.yellow('Line:'), err.lineNumber);
        }
        this.emit('end');
      }
    }))
    .pipe(babel())
    .pipe(gulp.dest('dist/js/'));
}

// Graceful degradation
function gracefulBuild() {
  return gulp.src('src/**/*.js')
    .pipe(plumber())
    .pipe(babel())
    .on('error', function(err) {
      log.error('Babel compilation failed, using original files');
      return gulp.src('src/**/*.js')
        .pipe(gulp.dest('dist/js/'));
    })
    .pipe(uglify())
    .pipe(gulp.dest('dist/js/'));
}

Testing

Unit Testing

const mocha = require('gulp-mocha');
const istanbul = require('gulp-istanbul');

// Run Mocha tests
function runTests() {
  return gulp.src('test/**/*.js', { read: false })
    .pipe(mocha({
      reporter: 'spec',
      timeout: 5000
    }));
}

// Code coverage
function coverage() {
  return gulp.src('src/**/*.js')
    .pipe(istanbul())
    .pipe(istanbul.hookRequire());
}

function testWithCoverage() {
  return gulp.src('test/**/*.js', { read: false })
    .pipe(mocha())
    .pipe(istanbul.writeReports())
    .pipe(istanbul.enforceThresholds({ thresholds: { global: 90 } }));
}

const testSuite = gulp.series(coverage, testWithCoverage);
exports.test = testSuite;

Integration Testing

const puppeteer = require('puppeteer');
const assert = require('assert');

// Browser testing
async function browserTest() {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto('http://localhost:3000');

  const title = await page.title();
  assert.strictEqual(title, 'My Website');

  await browser.close();
}

// Visual regression testing
const backstop = require('backstopjs');

function visualTest() {
  return backstop('test', {
    config: 'backstop.json'
  });
}

// Performance testing
const lighthouse = require('lighthouse');

async function performanceTest() {
  const results = await lighthouse('http://localhost:3000', {
    output: 'json',
    onlyCategories: ['performance']
  });

  const score = results.lhr.categories.performance.score * 100;
  console.log('Performance Score:', score);

  if (score < 90) {
    throw new Error('Performance score too low');
  }
}

Deployment

Build and Deploy Pipeline

const zip = require('gulp-zip');
const ftp = require('vinyl-ftp');

// Create deployment package
function createPackage() {
  return gulp.src('dist/**/*')
    .pipe(zip('deploy.zip'))
    .pipe(gulp.dest('packages/'));
}

// Deploy via FTP
function deployToServer() {
  const conn = ftp.create({
    host: process.env.FTP_HOST,
    user: process.env.FTP_USER,
    password: process.env.FTP_PASSWORD,
    parallel: 10,
    log: console.log
  });

  return gulp.src('dist/**/*', { base: 'dist', buffer: false })
    .pipe(conn.newer('/public_html'))
    .pipe(conn.dest('/public_html'));
}

// Complete deployment pipeline
const deploy = gulp.series(
  productionBuild,
  runTests,
  createPackage,
  deployToServer
);

exports.deploy = deploy;

CI/CD Integration

// Environment-aware deployment
function deployToEnvironment() {
  const env = process.env.NODE_ENV || 'development';
  const configs = {
    development: {
      host: 'dev.example.com',
      path: '/dev'
    },
    staging: {
      host: 'staging.example.com',
      path: '/staging'
    },
    production: {
      host: 'example.com',
      path: '/public_html'
    }
  };

  const config = configs[env];

  return gulp.src('dist/**/*')
    .pipe(deployTo(config));
}

// Docker deployment
function buildDockerImage() {
  return gulp.src(['dist/**/*', 'Dockerfile'])
    .pipe(docker.build({
      tag: 'my-app:latest'
    }));
}

// Kubernetes deployment
function deployToK8s() {
  return gulp.src('k8s/*.yaml')
    .pipe(kubectl.apply());
}

Best Practices

Project Organization

// Organized gulpfile structure
const { src, dest, watch, series, parallel } = require('gulp');

// Task modules
const styles = require('./gulp-tasks/styles');
const scripts = require('./gulp-tasks/scripts');
const images = require('./gulp-tasks/images');
const server = require('./gulp-tasks/server');

// Configuration
const config = require('./gulp.config.js');

// Export tasks
exports.styles = styles;
exports.scripts = scripts;
exports.images = images;
exports.serve = server.serve;
exports.build = parallel(styles, scripts, images);
exports.dev = series(exports.build, server.serve, server.watch);

Configuration Management

// gulp.config.js
module.exports = {
  paths: {
    src: 'src',
    dest: 'dist',
    styles: {
      src: 'src/scss/**/*.scss',
      dest: 'dist/css/'
    },
    scripts: {
      src: 'src/js/**/*.js',
      dest: 'dist/js/'
    },
    images: {
      src: 'src/images/**/*',
      dest: 'dist/images/'
    }
  },

  options: {
    sass: {
      outputStyle: 'compressed',
      includePaths: ['node_modules']
    },
    autoprefixer: {
      browsers: ['last 2 versions', '> 1%']
    },
    imagemin: {
      optimizationLevel: 5,
      progressive: true,
      interlaced: true
    }
  },

  server: {
    port: 3000,
    baseDir: 'dist'
  }
};

Performance Best Practices

  • Use incremental builds with gulp-changed or gulp-newer
  • Implement parallel processing for independent tasks
  • Cache expensive operations with gulp-cache
  • Use streaming instead of buffering for large files
  • Optimize watch patterns to avoid unnecessary rebuilds

Code Quality Best Practices

  • Implement linting for CSS, JavaScript, and HTML
  • Use source maps for debugging in development
  • Add error handling with gulp-plumber
  • Include testing in your build pipeline
  • Document your tasks and configuration

Maintenance Best Practices

  • Keep plugins updated regularly
  • Use semantic versioning for your builds
  • Implement proper logging for debugging
  • Create modular task files for better organization
  • Use environment variables for sensitive configuration

Summary

Gulp is a powerful streaming build system that excels at automating repetitive tasks in web development. Key features include:

  • Stream-based Processing: Efficient file processing without temporary files
  • Code over Configuration: JavaScript-based configuration for maximum flexibility
  • Rich Plugin Ecosystem: Thousands of plugins for every conceivable task
  • Parallel Processing: Run tasks simultaneously for faster builds
  • Watch and Live Reload: Automatic rebuilds and browser refresh
  • Incremental Builds: Process only changed files for speed
  • Error Handling: Robust error handling to prevent build failures
  • Extensible: Easy to create custom plugins and tasks

By leveraging Gulp's streaming architecture and extensive plugin ecosystem, you can create efficient, maintainable build processes that scale with your project's complexity.