In the last article, we talked about Grunt. You can check out this article at the link below:
Getting to Know Grunt: The Task Runner in JavaScript
When it was launched in 2012, Grunt was very successful and started to be used by many developers. However, in 2013, Gulp was launched and today it is much more used and known, with the impressive mark of approximately 1,300,000 downloads per week.
In this article, we will discuss its features, already focusing on its latest version, 4.0, and we will understand why it is so widely used. The truth is that Gulp is quite simple to implement and faster than Grunt. In addition, its configuration file is smaller. All of this leads many people to choose to use Gulp.
To make a comparison between these two automation tools, we will use the same project we created in the previous article, but now we will use Gulp.
How to Install Gulp?
Gulp, like Grunt, was developed in JavaScript and runs in the Terminal. Therefore, we will use Node.js once again. Remember that if you do not have Node, you can check out our video on YouTube where we teach how to install this tool by clicking here.
Now let's install Gulp through the command line. To do this, run the following in the Terminal:
npm install gulp-cli -g
With this command, we will install the Gulp CLI on our computer globally, making it accessible in any project.
Adding Gulp to the Project
The folder structure will be the same as the Grunt project. It will be necessary to start a Node project in this directory. So, we will run npm init -y in our Terminal.
The first module we will install is Gulp itself. We will execute the following command:
npm install gulp --save-dev
The next step will be to create a file called gulpfile.js in our root directory. We will import the Gulp module with the following line of code:
const gulp = require('gulp');
Now we are ready to develop our examples. Perhaps you have already seen in some documentation or tutorial about gulp.task(), which is responsible for creating a task in Gulp. This method still exists. However, in version 4.0, the way to create tasks has changed a little. Now it is recommended that we create a function that will define what the task will perform. Then, we should export that function via exports from Node with an identifier. And this identifier will be recognized as the task name. Let's create a first example to understand this better. We will create the task that will combine all CSS files into one and then minify it.
For this first task, we will need three modules: 1) gulp-concat (responsible for combining the files), 2) gulp-cssmin (responsible for minifying the files), and gulp-rename (responsible for renaming the files, if we wish). To install all three at once, we will run the following command:
npm install gulp-concat gulp-cssmin gulp-rename --save-dev
To import them into the project, we will use the following code:
const concat = require('gulp-concat');
const cssmin = require('gulp-cssmin');
const rename = require('gulp-rename');
Let's create our first function, which we will call stylesMethod(). It will have the following syntax:
function stylesMethod() {
return gulp.src("./assets/css/*.css")
.pipe(concat("all.css"))
.pipe(cssmin())
.pipe(rename({ suffix: ".min" }))
.pipe(gulp.dest("./dist"))
;
}
Explaining: we use the src() method of the gulp module to find all our CSS files inside the desired folder. We also use the pipe() method, which is associated with a very interesting concept of Node.js which are streams. This method is one of the key reasons for Gulp’s excellent performance.
Within each pipe() method, we execute some function. We execute concat(), informing the name of the file that will be generated after concatenation, we use cssmin() to minify that same file, we call rename() to add the suffix “.min” to the final file and, finally, we use another Gulp method called .dest() to set the directory where we want the final file to be saved. Just one detail: it is very important to use return in the functions, so that no error is returned in the Terminal.
And our function is ready. Now we need to export it as a task. To do this, just use the following line of code at the end of the file:
exports.styles = stylesMethod;
The task will be called styles. To test it, just run the following in the Terminal:
gulp styles
When doing this, we see the following result:
The task was executed correctly and without errors. If we go to the dist folder, we will find the file all.min.css, with the following content:
Our file was correctly minified and concatenated, and our task was much smaller compared to the Grunt file. Much simpler, don't you agree?
Now let's do the same for the JavaScript files. We will download only the gulp-uglify module for minifying the files (we could also use gulp-jsmin if we wanted). To install it, we will execute the following command:
npm install gulp-uglify --save-dev
The import in our code will look like this:
const uglify = require('gulp-uglify');
We will create a function called scriptsMethod(), which will contain the following syntax:
function scriptsMethod() {
return gulp.src("./assets/js/*.js")
.pipe(concat("all.js"))
.pipe(uglify())
.pipe(rename({ suffix: ".min" }))
.pipe(gulp.dest("./dist"));
}
Note that we were able to reuse the other modules we had already installed. Only uglify() was different. To export this function as a task, we will use the following code:
exports.scripts = scriptsMethod;
To test this task, we will run gulp scripts in our Terminal. The result will be as follows:
The task executed correctly, excellent! If we go to the dist directory, we will find the file all.min.js, with the following content:
It is indeed more practical to use Gulp. Before we continue, let's do a small refactor. The Gulp module is very extensive. Thus, requiring the entire module can make our project a bit heavier. One alternative to solve this issue is to use the Destructuring Assignment feature (difficult word, huh) that was implemented in the ES6 version of JavaScript, or EcmaScript2015. This assignment involves requiring only a part of the module, using braces for that. In the case of the gulp module, we use two methods: src() and dest(). To request only these two resources, we will leave the first line of the gulpfile.js like this:
const { src, dest } = require('gulp');
This way, our code becomes lighter. And now, instead of calling gulp.src() or gulp.dest(), we will use only the method names, which will make our functions look like this:
function stylesMethod() {
return src("./assets/css/*.css")
.pipe(concat("all.css"))
.pipe(cssmin())
.pipe(rename({ suffix: ".min" }))
.pipe(dest("./dist"));
}
function scriptsMethod() {
return src("./assets/js/*.js")
.pipe(concat("all.js"))
.pipe(uglify())
.pipe(rename({ suffix: ".min" }))
.pipe(dest("./dist"));
}
You can learn more about the resources of EcmaScript2015, as well as all of JavaScript, in our Complete JavaScript Course, where we create seven real projects using this incredible language.
Now that we have made this small refactor, let's implement the last module, watch(). Unlike Grunt, where we need to download an external module for this task, Gulp has a built-in module for that. To import it into our project, just add watch to our destructuring assignment:
const { src, dest, watch } = require('gulp');
Let's create a function that will watch for changes in the files of our directories. Its content will be as follows:
function watchFiles() {
watch("./assets/css/*.css", stylesMethod);
watch("./assets/js/*.js", scriptsMethod)
;
}
Explaining: it is not necessary to define the return for the watch() method. We execute it twice. The first parameter of this method involves informing which files should be “watched,” and the second parameter defines the function that will be executed when the files are changed.
We will export this function as the default method of Gulp. Thus, when executing just gulp in the Terminal, we will already be watching for changes in the files. To perform this export, we will define the function in the default property of exports, with the following code:
exports.default = watchFiles;
Now, when we run gulp, we see the following result in the Terminal
And, when changing any JS or CSS file, we will see the following:
We see that the tasks are executed and Gulp continues to watch for changes for us.
Conclusion
Through these examples, we were able to understand Gulp's resources, along with the news of its version 4.0. We realized that it is indeed simpler, more readable, and easier to implement in our projects. Additionally, it is quite fast. If you're in doubt about whether to use Gulp or not, you can install it without fear; it is an amazing tool!
You can find the codes developed in this article on our GitHub.
If you liked this content, don't forget to share it with others; it helps us a lot. Is there any other topic (language, tool, tutorial) you would like to read about on our Blog? You can send your suggestions by clicking here.
Until the next article! :)