Gulp! My assets pipeline 2.0 on WIndows

Posted
Categorized as Code, Software Tagged , , ,
image

This is an update to my previous setup I wrote about on: How I build my assets pipeline on Windows using NodeJS. This time around I use Gulp to simplify things and add more automation.

First up, you’ll need to install gulp globally (npm i -g gulp) if you haven’t yet, then install it in your project directory (npm i gulp -D). The goal is accomplish the following automatically:

  • compile and minify my javascript files when changes are made
  • compile and compress my sass into css when changes are made
  • automatically reload my browser when the css/js is compiled

Here’s a list of the plugins I use and what they in relation to my workflow. This assumes you are familiar with NodeJS already, if not you may read this post first.

Some none-gulp plugins we’ll also need are:

Once you have all these installed, create a gulpfile.js in your project directory (where your package.json is) then you can start creating task. In my setup, I simply run the gulp command to watch my JavaScript and sass files, compile them, and reload the browser. I have a different gulp task to compress the images since this is not done often. Note that the paths may vary depending on how you structure your working environment.

var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css');
var terser = require('gulp-terser');
var concat = require('gulp-concat');
var es = require('event-stream');
var merge = require('merge-stream');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var livereload = require('gulp-livereload');
var imagemin = require('gulp-imagemin');
var imageminPngquant = require('imagemin-pngquant');
var imageminZopfli = require('imagemin-zopfli');
var imageminMozjpeg = require('imagemin-mozjpeg');

gulp.task('scripts', function() {
	var results = [];
	results.push(browserify('client/index.js')
			.bundle()
			.pipe(source('bundle.min.js'))
			.pipe(buffer())
			.pipe(terser())
			.pipe(gulp.dest('public/assets/js')));

	results.push(browserify('client/index.js')
			.bundle()
			.pipe(source('bundle.js'))
			.pipe(buffer())
			.pipe(gulp.dest('public/assets/js')));
	return merge(results);
});

gulp.task('styles', function() {
	var sassStream = gulp.src('client/*.scss')
						.pipe( sass({ 
								outputStyle: 'expanded', 
								errLogToConsole: true 
							}) 
						);
	var results = [];

	results.push(es.merge(sassStream)
				.pipe(concat('bundle.min.css'))
				.pipe(autoprefixer())
				.pipe(cleanCSS({}))
				.pipe(gulp.dest('public/assets/css'))
				.pipe(livereload()));

	results.push(es.merge(sassStream)
				.pipe(concat('bundle.css'))
				.pipe(autoprefixer())
				.pipe(cleanCSS({
					format:{
						breaks: { 
							afterAtRule: true,
							afterBlockBegins: true,
							afterBlockEnds: true,
							afterComment: true,
							afterProperty: true,
							afterRuleBegins: true,
							afterRuleEnds: true,
							beforeBlockEnds: true,
							betweenSelectors: true
						},
						spaces: {
							aroundSelectorRelation: true,
							beforeBlockBegins: true,
							beforeValue: true
						},
						indentBy:1,
						indentWith: 'tab'
					}
				}))
				.pipe(gulp.dest('public/assets/css'))
				.pipe(livereload()));
	return merge(results);
});

gulp.task('images', function() {
	return gulp.src('client/img/*.{jpg,png,svg,gif}')
				.pipe(imagemin([
					//gif lossless
					imagemin.gifsicle({
						interlaced: true,
						optimizationLevel: 3
					}),
					//svg
					imagemin.svgo({
						plugins: [{
							removeViewBox: false
						}]
					}),
					//png lossless
					imageminPngquant(),
					imageminZopfli({
						more: true
					}),
					//jpg lossless
					imagemin.jpegtran({
						progressive: true
					}),
					//jpeg lossy
					imageminMozjpeg({
						quality: 90
					})
				]))
				.pipe(gulp.dest('public/assets/img'))
});

gulp.task('default', function() {
	livereload.listen();
	gulp.watch('client/*.js', gulp.series('scripts'));
	gulp.watch('client/*.scss', gulp.series('styles'));
	gulp.watch('client/img/*.*', gulp.series('images'));
});

UPDATE April 5, 2018fix for deprecated packages and missing Python executable. UPDATE: October 6, 2018 – I updated the image compress gulp task for better compression and added SVG, and GIF support. Also added the default task to trigger image compression when the source image folder contents are updated. Website Planet has an  image compression tool which inspired this update.

UPDATE October 11, 2019 – updated the gulp plugin dependency changes and added a non-minified version of the bundled CSS and JS files


Leave a Reply