Welcome to the second part of our tutorial on Gulp build system. In the previous part we saw how we can set up a simple build system based on Gulp.
We were able to install node, npm
, and gulp
. Then we created a simple gulpfile.js
in which we defined a simple task that could minify our css.
Based on that little exercise we had noticed that every time we make any changes, we have to go back to our command line and run gulp mincss
which is our task name. Until then, our system was not automatic. We wish it could do that job every time we use ctrl+s
. Beside, we want it to refresh our browser for us and prompt a notification to tell us if the tasks were executed successfully.
Once again welcome to this part. I am zooboole your tutor all along this tutorial.
In this part I will take you to the discovery of our third section of the gulpfile.js
which will allow us to watch
our files and run our tasks runners whenever we save. also, aside our minified css task, we are going to add the possibility of compiling a sass file instead of using raw css, then display a notification when everything is done successfully.
From here you should know that all this jobs or tasks correspond to gulp packages that we need to download in our project.
To start, here is my current folder structure:
- Build/
- index.html
- package.json
- gulpfile.js
- node_modules/
- gulp/
- gulp-minify-css/
- main.css
Install required packages
cd
to your project folder and run the following commands one by one to install the required packages:
npm install --save-dev gulp-notify
npm install --save-dev gulp-sass
Add a watch task and automate the system
Gulp provides an object called watch
which is just like the src
and the dest
objects. We can use the watch
object to ask gulp to watch over a given task. That means that Gulp will surveil the file in case it\'s modified.
Add the following code to your gulpfile.js
to start watching your main.css
file:
gulp.watch(\'main.css\', function(){
console.log(\'seen\');
});
Your final gulpfile.js should look like this:
var gulp = require(\'gulp\');
var minifyCss = require(\'gulp-minify-css\');
gulp.task(\'mincss\', function(){
return gulp.src(\'main.css\')
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'));
});
gulp.watch(\'main.css\', function(){
console.log(\'seen\');
});
Now go to your command line and run gulp mincss
again. If everything happened as expected you should see a message: seen like in the image below:
The watch
object will still be listening to any changes made in the main.css
file, and display seen
everytime until you press ctrl+c
to stop it. Cool!
The watch function takes two arguments: the file(s) to watch and a call to action. The second argument can be a closure (anonymous function) or a javascript object.
Notice that in time we may be adding more tasks to our gulpfile.js
file. We could have a task script to manage our javascript files, a task connectPHP to run a php server, etc. It could become hard to manage it with this way of watching. Let assume we have three files to watch, we will have to write:
gulp.watch([\'file1.css\', \'file2.txt\', \'file3.js\'], function(){
console.log(\'seen\');
});
It will work fine, but I personaly have two main problems with this practice: One, it looks dirty. I have to write the whole file name. Two, it\'s going to display the same massage (\'seen\') everytime any of the files is changed, while I wish I could know when a particular file is changed.
The best way to handle the dirty part is to create an object of paths like following:
var paths = {
css:[\'path/to/style1.css\', \'path/to/style2.css\'],
script:[\'path/to/script1.js\', \'path/to/script2.js\']
};
gulp.watch(paths.css, function(){
console.log(\'seen css changes\');
});
gulp.watch(paths.script, function(){
console.log(\'seen javascript changes\');
});
That looks good, and gives us the chance to know when our css is changed or when is our javascript is changed.
Another powerful thing to notice is the second argument. Since we can use a closure as argument, imagine we pass in there a whole task? so that we have something like this:
gulp.watch(paths.css, [\'mincss\']);
You agree with me that, this looks so clean. Now, with all these little changes, let\'s apply it to our gulp file and see how it looks in overall:
var gulp = require(\'gulp\');
var minifyCss = require(\'gulp-minify-css\');
var paths = {
css:[\'main.css\'],
text:[\'test.txt\']
};
gulp.task(\'mincss\', function(){
return gulp.src(\'main.css\')
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'));
});
gulp.watch(paths.css, [\'mincss\']);
While all this is fine, imagine we have more tasks to watch. How do we run it from our command line? Let assume the following case:
var gulp = require(\'gulp\');
var minifyCss = require(\'gulp-minify-css\');
var coffee = require(\'gulp-coffee\');
var paths = {
css:[\'main.css\'],
script:[\'script.coffee\']
};
gulp.task(\'mincss\', function(){
return gulp.src(\'main.css\')
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'));
});
gulp.task(\'scripts\', function(){
return gulp.src(paths.script)
.pipe(coffee())
.pipe(gulp.dest(\'js\'));
});
gulp.watch(paths.css, [\'mincss\']);
gulp.watch(paths.script, [\'scripts\']);
When you run gulp mincss
it will be watching the css file and our coffee script file. But when you change the coffee script file, it will no be watched, the css file will not be watched either. Meaning, the watching happen only when you change your css file. Same thing happens when you decide to watch the script task. Though this could be usefull sometimes in terms of savings of resources.
To palliate to the problem we need to gather all tasks watched into a single watching task that can be called once and it could watch all our tasks at once:
var gulp = require(\'gulp\');
var minifyCss = require(\'gulp-minify-css\');
var coffee = require(\'gulp-coffee\');
var paths = {
css:[\'main.css\'],
script:[\'script.coffee\']
};
gulp.task(\'mincss\', function(){
return gulp.src(\'main.css\')
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'));
});
gulp.task(\'scripts\', function(){
return gulp.src(paths.script)
.pipe(coffee())
.pipe(gulp.dest(\'js\'));
});
gulp.task(\'watcher\',function(){
gulp.watch(paths.css, [\'mincss\']);
gulp.watch(paths.script, [\'scripts\']);
});
Then all you have to do is to run gulp watcher
and all your files will be watched at the same time. Any file you change will be compiled.
There is another way to make things simpler. Instead of you to run gulp watcher
you can just run gulp
and it will do the work for you. But, right now in our case if you enter gulp
you will receive this error:
[11:08:34] Task \'default\' is not in your gulpfile
[11:08:34] Please check the documentation for proper gulpfile formatting
Gulp is requesting us to create another task that we must be named default
which is necessary to its functioning.
So, what\'s the default task about? This task takes all the tasks to run in one single object including our watcher
task. Now we can change our gulpfile.js
into this:
var gulp = require(\'gulp\');
var minifyCss = require(\'gulp-minify-css\');
var coffee = require(\'gulp-coffee\');
var paths = {
css:[\'main.css\'],
script:[\'script.coffee\']
};
gulp.task(\'mincss\', function(){
return gulp.src(\'main.css\')
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'));
});
gulp.task(\'scripts\', function(){
return gulp.src(paths.script)
.pipe(coffee())
.pipe(gulp.dest(\'js\'));
});
gulp.task(\'watcher\',function(){
gulp.watch(paths.css, [\'mincss\']);
gulp.watch(paths.script, [\'scripts\']);
});
gulp.task(\'default\', [\'watcher\', \'mincss\',\'scripts\']);
I love this one <3.
Compile sass file
To compile a sass file, require our gulp-sass
package.
var sass = require(\'gulp-sass\');
Remain your main.css
file into main.scss
Pipe it in your css task (even though you can still create a different task for it.)
gulp.task(\'mincss\', function(){
return gulp.src(\'main.scss\')
.pipe(sass().on(\'error\', sass.logError))
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'));
});
Now delete every thing you have in main.scss
and add following code:
$color-title: #333;
h1{
color:$color-title;
}
Run you gulp
command. Now if you check main/main.css
you should see:
h1{color:#333}
Happy Sassing!
Display a notification
Adding a notification is one of the easiest things to do with gulp. Just require gulp-notify
in your gulpfile.js
var notify = require(\'gulp-notify\');
Then pipe your css through it:
gulp.task(\'mincss\', function(){
return gulp.src(\'main.scss\')
.pipe(sass().on(\'error\', sass.logError))
.pipe(minifyCss())
.pipe(gulp.dest(\'main\'))
.pipe(notify(\'Done! master zooboole.\'));
});
All you have to do is just to pass a message to display to notify()
Then run gulp
. If every is well, you should see something like this:
Conclusion
Though I planned to introduce live reloading in this part I couldn\'t because it was getting too long. So I have decided to write a third part in this topic. The next part will be exclusively about live reloading.
Thanks for following and as usual, if you like share with others, or you can leave a comment.
Last updated 2024-01-11 UTC