JakeCobley
6/28/2017 - 11:52 AM

Generic Gulpfile for front-end development

Generic Gulpfile for front end development.

(function () {
  "use strict";

  /**
   * gulpfile.js
   *
   * Available tasks:
   *   `gulp`
   *   `gulp watch`
   *
   * Modules:
   *   gulp                       : The streaming build system.
   *   gulp-util                  : Utility functions for gulp plugins.
   *   fs                         : File System.
   *   del                        : Delete files and folders.
   *   path                       : Node.JS path module.
   *   merge-stream               : Create a stream that emits events from
   *                                multiple other streams.
   *   gulp-gulp-clip-empty-files : Clip empty files from stream.
   *   gulp-changed               : Only pass through changed files.
   *   gulp-jshint                : JSHint plugin for Gulp.
   *   gulp-uglify                : Minify files with UglifyJS.
   *   gulp-sass                  : Gulp plugin for sass.
   *   gulp-sourcemaps            : Source map support for Gulp.js.
   *   gulp-autoprefixer          : Prefix CSS.
   *   gulp-cssnano               : Minify CSS with cssnano.
   */
  var gulp = require('gulp');
  var $ = {
    util          : require('gulp-util'),
    fs            : require('fs'),
    del           : require('del'),
    path          : require('path'),
    mergeStream   : require('merge-stream'),
    clipEmptyFiles: require('gulp-clip-empty-files'),
    changed       : require('gulp-changed'),
    jsHint        : require('gulp-jshint'),
    uglify        : require('gulp-uglify'),
    sass          : require('gulp-sass'),
    sourcemaps    : require('gulp-sourcemaps'),
    autoPrefixer  : require('gulp-autoprefixer'),
    cssNano       : require('gulp-cssnano')
  };

  /**
   * Config
  */
  var root = {
    src: './src',
    dest: './dist'
  };

  var tasks = {
    clean: {
    },

    images: {
      src: 'img',
      dest: 'img',
      exclude: 'img/vectors',
      extensions: [
        'jpg',
        'png',
        'svg',
        'gif'
      ]
    },

    js: {
      src: 'js',
      dest: 'js',
      extensions: [
        'js'
      ]
    },

    css: {
      src: 'scss',
      dest: 'css',
      extensions: [
        'scss'
      ],
      plugins: {
        autoPrefixer: [
          'last 2 versions'
        ],
        cssNano: {
          zindex: false,
          reduceIdents: false,
          mergeIdents: false,
          discardUnused: false
        }
      }
    }
  };

  /**
   * Returns list of sub folders within a directory
   * @param {string} str - path to directory
   * @return {array} array
  */
  function getFolders(dir) {
    return $.fs.readdirSync(dir)
      .filter(function(file) {
        return $.fs.statSync($.path.join(dir, file)).isDirectory();
      });
  }

  /**
   * Deletes dist directory
  */
  function clean() {
    return $.del([
      root.dest
    ]);
  }

  /**
   * JSHint and minify javascript files
  */
  function js() {
    return gulp.src(root.src + '/' + tasks.js.src +  '/**/*.' + tasks.js.extensions)
      .pipe($.jsHint())
      .pipe($.jsHint.reporter('default'))
      .pipe($.util.env.production ? $.uglify() : $.util.noop())
      .pipe(gulp.dest(root.dest + '/' + tasks.js.dest + '/'));
  }

  /**
  * Clips empty files from the stream, sourcemaps (if not production),
  * autoprefixes css, combines media queries, minifies css
  */
  function css() {
    return gulp.src(root.src + '/' + tasks.css.src + '/**/*.' + tasks.css.extensions)
      .pipe($.clipEmptyFiles())
      .pipe(!$.util.env.production ? $.sourcemaps.init() : $.util.noop())
      .pipe(!$.util.env.production ? $.sass.sync().on('error', $.sass.logError) : $.util.noop())
      .pipe($.util.env.production ? $.sass.sync() : $.util.noop())
      .pipe($.autoPrefixer(tasks.css.plugins.autoPrefixer))
      .pipe(!$.util.env.production ? $.sourcemaps.write() : $.util.noop())
      .pipe($.util.env.production ? $.cssNano(tasks.css.plugins.cssNano) : $.util.noop())
      .pipe(gulp.dest(root.dest + '/' + tasks.css.dest + '/'));
  }

  /**
   * Watches files for changes
  */
  function watch() {
    gulp.watch(root.src + '/' + tasks.vendor.src + '/**/*', vendor);
    gulp.watch(root.src + '/' + tasks.images.src + '/**/*', images);
    gulp.watch(root.src + '/' + tasks.svgSprite.src + '/**/*', svgSprite);
    gulp.watch(root.src + '/' + tasks.js.src + '/**/*', js);
    gulp.watch(root.src + '/' + tasks.css.src + '/**/*', css);
  }

  /**
   * Combines clean, vendor, images, svgSprite, js and css tasks.
  */
  var build = gulp.series(
    clean,
    gulp.parallel(
      gulp.series(
        images,
        svgSprite
      ),
      js,
      css
    )
  );

  /**
   * Gulp tasks
  */
  exports.default = build;
  exports.watch = watch;

}());