Build Wars
@markdalgleish
Gulp vs Grunt
A brief history of Grunt
I realized that a task-based build tool with built-in, commonly used tasks was the approach that would work best for me
Ben Alman
March 2012
Single, global Grunt:
$ npm install -g grunt
Configuration over code
grunt.initConfig({
lint: {
src: 'src/<%= pkg.name %>.js'
},
concat: {
src: [
'<banner:meta.banner>',
'<file_strip_banner:src/<%= pkg.name %>.js>'
],
dest: '<%= pkg.name %>.js'
}
});
Built-in init task to get you started
$ grunt init jquery
Kitchen sink
- init
- concat
- lint
- min
- qunit
- server
- test
- watch
Simple config
Common build steps
Designed for small libraries & plugins
OMG GRUNT
OMG GRUNT PLUGINS
What was wrong?
- Global 'grunt' command...
- Upgrading Grunt could break older projects
- Your new project might not build on old Grunt versions
- Grunt was really only designed for small projects
Grunt v0.4
Released Feb 2013
- grunt.js became Gruntfile.js
- 'init' task became 'grunt-init', inspired Yeoman
- Local Grunt install for each project
- Global 'grunt' command runs local Grunt
- Everything is a plugin, no built-in tasks
GRUNT 0.4
+
BOWER
+
YEOMAN
A CHALLENGER APPEARS
- Stream-based build system
- Code over configuration
- Small, idiomatic Node modules
- Really simple, elegant API
Basic Gulpfile
var gulp = require('gulp'),
stylus = require('gulp-stylus'),
autoprefixer = require('gulp-autoprefixer');
gulp.task('default', function() {
return gulp.src('src/styles/*.styl')
.pipe(stylus())
.pipe(autoprefixer())
.pipe(gulp.dest('public/styles'));
});
Gulp tasks run from terminal
$ gulp taskname
Streaming Builds
gulp.src('src/foobar.styl') // <-- Read from FS
// In memory transforms:
.pipe(stylus())
.pipe(rename({ ext: 'css' }))
.pipe(autoprefixer())
.pipe(cssmin())
.pipe(header('/* Copyright 2014 */'))
.pipe(gulp.dest('dist')) // <-- Write to FS
Streams?
Read the Stream Handbook
by @substack
best part about @gulpjs is that people are writing generic, streaming node modules that have nothing to do w/ gulp except the module name :)
LET'S LEARN THE GULP API
It's not too hard.
gulp.task
gulp.task('name', ['deps'], function(done) {
return stream || promise;
// ...or, call done()
});
gulp.watch
gulp.watch('src/**/*.js', ['test', 'compile']);
gulp.src
Returns a readable stream
gulp.src(['src/**/*.js', 'test/spec/**/*.js'])
gulp.dest
Returns a "through stream"
gulp.src('src')
.pipe(...)
.pipe(gulp.dest('dist'));
Yes, that means you can keep piping!
task, watch, src, dest
That's it.
But...
How do you run all the tasks sequentially?
WRONG QUESTION
Gulp uses Orchestrator
Just specify task dependencies
Tasks run with maximum concurrency
But...
What's coming down the pipe?
vinyl
Virtual file objects
USING GULP IN ANGER
Bespoke.js
Now uses Gulp instead of Grunt
Which caused me to write...
gulp-coveralls
Submits unit test coverage to coveralls.io
So...
Is Gulp ready to replace Grunt?
Well, not unless you live on the bleeding edge
The ecosystem needs a bit more time to mature
First things first...
OMG GULP PLUGINS
284 and counting...
Gulp is a new, fast & light, streaming build system. While evaluating it for @yeoman I created some plugins for it: http://j.mp/1fnwFpv
@sindresorhus
Dec 19, 2013
Two weeks later...
26 @gulpjs plugins done! https://github.com/search?l=&o=de…
for: #reactjs, mocha, webp, myth, traceur, recess, esformatter, jscs, ftp, tar, zip, & more
@sindresorhus
Jan 2, 2014
So...
What's happening with Yeoman?
There's already an official generator for Gulp
generator-gulp-webapp
THE YEOMAN TEAM AGREES
Gulp is awesome.
(I agree too)
THE FUTURE
- node-task spec for standardised build tasks (Grunt is on board)
- Grunt 1.0 alpha uses Orchestrator! (OMG)
- So what's the difference? Config vs code.