A while ago, I wrote an article about a basic Grunt setup for building. But as some of you might already know for some time now, the streamed task runner Gulp is winning more and more popularity in the fields of web development. I’ve also tasted a bit of Gulp myself (not as much as Grunt since I prefer proven technology) but nevertheless I’ve got a basic Gulp setup for building a website. And it nicely integrates with Continuous Integration processes like Jenkins for example. So let’s just have a look at it shall we?
The Gulp modules
The Gulp modules I use are:
- gulp-sass
- gulp-autoprefixer
- gulp-sourcemaps
- gulp-minify-css
- gulp-combine-mq
- gulp-uglify
- gulp-concat
- run-sequence
- gulp-livereload
Or as you will:
1 2 3 4 5 6 7 8 9 |
npm install --save-dev gulp-sass npm install --save-dev gulp-autoprefixer npm install --save-dev gulp-sourcemaps npm install --save-dev gulp-minify-css npm install --save-dev gulp-combine-mq npm install --save-dev gulp-uglify npm install --save-dev gulp-concat npm install --save-dev run-sequence npm install --save-dev gulp-livereload |
The gulpfile.js
And without any further adieu, here’s the content of my gulpfile.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
var gulp = require('gulp'), sass = require('gulp-sass'), autoprefixer = require('gulp-autoprefixer'), sourcemaps = require('gulp-sourcemaps'), minifycss = require('gulp-minify-css'), combineMq = require('gulp-combine-mq'), uglify = require('gulp-uglify'), concat = require('gulp-concat'), runSequence = require('run-sequence'), livereload = require('gulp-livereload'); // --- [DEV TASKS] --- // SASS the heck out of this project: gulp.task('sass', function() { return gulp.src('path/to/scss/screen.scss') .pipe(sourcemaps.init()) .pipe(sass({ precision: 10, onError: console.error.bind(console, 'Sass error:') })) .pipe(sourcemaps.write({includeContent: false})) .pipe(gulp.dest('path/to/css')); }); // Concatenate all JS into one script: gulp.task('js', function() { return gulp.src( ['path/to/js/scripts/*.js', 'path/to/js/global.js']) .pipe(sourcemaps.init()) .pipe(concat('scripts.js')) .pipe(sourcemaps.write('.')) .pipe(gulp.dest('path/to/js')); }); // Watcher: gulp.task('watch', function () { // Create LiveReload server livereload.listen(); // Watch .scss files gulp.watch('path/to/scss/**/*.scss', ['sass']) .on('change', livereload.changed) ; gulp.watch('path/to/js/**/*.js', ['js']); }); // --- [BUILD TASKS] --- // Make the CSS as small and optimized as possible: gulp.task('build-css', function() { return gulp.src('path/to/scss/screen.scss') .pipe(sass({ precision: 10, onError: console.error.bind(console, 'Sass error:') })) .pipe(autoprefixer()) .pipe(combineMq()) .pipe(minifycss()) .pipe(gulp.dest('path/to/css')); }); // Concatenate and uglify JS: gulp.task('build-js', function() { return gulp.src( ['path/to/js/scripts/*.js', 'path/to/js/global.js']) .pipe(concat('scripts.js')) .pipe(uglify()) .pipe(gulp.dest('path/to/js')); }); // Setup the build: gulp.task('build', function (cb) { // CSS and JavaScript: runSequence('build-css', 'build-js', cb); }); |
As you might notice, I’ve created 2 ‘sections’: One for the development (dev) tasks, which I use when I’m working locally, and one for the build task that is ran by our Continuous Integration server.
Development tasks
These tasks are here to render my SCSS and concatenate my JavaScript files (more on that further on in this article). The watcher and live reload plugin makes sure everything gets updated automatically while I’m working on them. It also provides source maps that help me track down code in the separate SCSS/JS files when I’m tracing my code or stylesheets. When I’m going to work on the project, a simple gulp watch in the terminal will do.
Build tasks
The build tasks are almost identical to the development tasks but with 2 small differences:
- They don’t create source maps. We don’t need those on a live site.
- They minify and uglify the heck out of my CSS and JS. But it saves bandwidth and that’s cool.
Our Continuous Integration server is set to execute a gulp build to do all this magic for us.
Concatenating JavaScript
When I’m writing JavaScript, I like to keep my code as clean and separated as possible. I set up my JavaScript as prototype-classes for each functionality and treat them like such. That’s why I create separated files for each JavaScript class and let Gulp concatenate (and minify/uglify) these files for me while I’m at it. In my website, I only need to create one <script> -tag with one JavaScript file which is the sum of all my separate JavaScript files.
In conclusion
Gulp is a great tool with great benefits. It’s community is very active but since it’s newer than Grunt some plugins might not work as well as you might expect. For example, the source maps of gulp-ruby-sass don’t work out of the box at the moment of writing, that’s why I use the non-ruby version called gulp-sass . It’s yet to determine which of these will be one eventually most used by the developers worldwide. And that’s just one example.
Grunt on the other hand has already a pretty proven track-record, that’s why I didn’t work much with Gulp earlier (that, and I’ve been doing huge backend-jobs for the last couple of months).
Will there be a place for two task runners? Will one become bigger and in time destroy the competition? I don’t know. One major benefit of Gulp is it’s simplicity and it’s speed since it works with streams instead of files. But how long will it take until Grunt will also get a stream-like processing system? In the end I think it comes down to a question of developers taste and proven technology.
Visitors give this article an average rating of 4.4 out of 5.
How would you rate this article?
★ ★ ★ ★ ★