5 Lessons Learned Using gulp.js
Using gulp.js isn't always straightforward. Here are a couple of tips to help you out.
1. Things don't run in sequence
With gulp.js tasks don't run in the order you define them. In fact they run in concurrently to make the total execution faster.
If you however want run tasks in order, you can define dependencies like this:
gulp.task('one', function (cb) {
cb(err);
});
gulp.task('two', ['one'], function () {});
gulp.task('default', ['one', 'two']);
In previous versions of gulp, you should have used something like gulp-sequence or run-sequence.
2. Watch carefully
When you watch for changes in files, make sure to only watch the files that change on a regular basis.
// Yes
gulp.watch('src/js/**/*.js', ['js']);
// No
gulp.watch('**/*.*', ['js']);
Otherwise running the gulp
task in the command line will result in a slower tasks and high CPU / memory usage.
3. Gulp-inject
After concatenating and minifying CSS and JavaScript files, I wanted to find a way to dynamically add those files to the HTML page. gulp-inject was the plug-in that did the trick for me.
// Make sure all the previous tasks (concatenation / minification) are run first
gulp.task('index', ['images', 'js', 'css', 'fonts'], function () {
var inject = require('gulp-inject');
var target = gulp.src('./src/index.html');
// Read = false will not read the file contents and make the task faster
var sources = gulp.src([paths.build.js, paths.build.css], {
read: false,
});
return target
.pipe(
inject(sources, {
// Do not add a root slash to the beginning of the path
addRootSlash: false,
// Remove the `public` from the path when doing the injection
ignorePath: 'public',
})
)
.pipe(gulp.dest('public'));
});
And this is the html
part:
<body>
<!-- inject:js -->
<!-- endinject -->
</body>
Next to html
, it also supports jade
, jsx
, slm
and haml
.
4. Using bower?
When you're using bower to manage your dependencies, main-bower-files will come in handy. Otherwise you'll have to manually define which bower files you want to include.
var mainBowerFiles = require('main-bower-files');
var paths = {
src: {
js: mainBowerFiles({
// Set the base path for your bower components
base: './bower_components',
// Only return the JavaScript files
filter: /.*\.js$/i
// Concatenate the bower files with your own
}).concat(['src/js/**/*.js']);
}
}
5. Node + browsersync: possible but cumbersome
One of the most tedious parts was finding a way to make gulp work with nodemon (automatically restart node) and BrowserSync. The gulpfile from Hafiz Ismail was a great start and I made some small changes.
gulp.task('nodemon', function (cb) {
var nodemon = require('gulp-nodemon');
// We use this `called` variable to make sure the callback is only executed once
var called = false;
return nodemon({
script: 'server.js',
watch: ['server.js', 'server/**/*.*'],
})
.on('start', function onStart() {
if (!called) {
cb();
}
called = true;
})
.on('restart', function onRestart() {
// Also reload the browsers after a slight delay
setTimeout(function reload() {
browserSync.reload({
stream: false,
});
}, 500);
});
});
// Make sure `nodemon` is started before running `browser-sync`.
gulp.task('browser-sync', ['index', 'nodemon'], function () {
var port = process.env.PORT || 5000;
browserSync.init({
// All of the following files will be watched
files: ['public/**/*.*'],
// Tells BrowserSync on where the express app is running
proxy: 'http://localhost:' + port,
// This port should be different from the express app port
port: 4000,
// Which browser should we launch?
browser: ['google chrome'],
});
});
Conclusion
Hope you all taken something away from this post, if you have any remarks / comments, feel free to contact me on twitter.
I love to share interesting ideas.