Understanding the Basics of Gulp

In this chapter, we will take a look at the basics of Gulp and how it works. Understanding some of the basic principles and philosophies behind the tool, it's plugin system will assist you as you begin writing your own gulpfiles. We'll start by taking a look at the engine behind Gulp and then follow up by breaking down the inner workings of Gulp itself. By the end of this chapter, you will be ready to begin writing your own gulpfile.

Installing Node.js and npm

As you learned in the introduction, Node.js and npm are the engines that work behind the scenes that allow us to operate Gulp and keep track of any plugins we decide to use.

Downloading and installing Node.js

For Mac and Windows, the installation is quite simple. All you need to do is navigate over to http://nodejs.org and click on the big green install button. Once the installer has finished downloading, run the application and it will install both Node.js and npm.

For Linux, there are a couple more steps, but don't worry; with your newly acquired command-line skills, it should be relatively simple. To install Node.js and npm on Linux, you'll need to run the following three commands in Terminal:

sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
The details of these commands are outside the scope of this book, but just for reference, they add a repository to the list of available packages, update the total list of packages, and then install the application from the repository we added.

Verify the installation

To confirm that our installation was successful, try the following command in your command line:

node -v

If Node.js is successfully installed, node -v will output a version number on the next line of your command line. Now, let's do the same with npm:

npm -v

Like before, if your installation was successful, npm -v should output the version number of npm on the next line.

The versions displayed in this screenshot reflect the latest Long Term Support (LTS) release currently available as of writing this. This may differ from the version that you have installed, depending on when you're reading this. It's always suggested that you use the latest LTS release when possible.

The -v  command is a common flag used by most command-line applications to quickly display their version number. This is very useful to debug version issues while using command-line applications.

Creating a package.json file

Having npm in our workflow will make installing packages incredibly easy; however, we should look ahead and establish a way to keep track of all the packages (or dependencies) that we use in our projects. Keeping track of dependencies is very important to keep your workflow consistent across development environments.

Node.js uses a file named package.json to store information about your project, and npm uses this same file to manage all of the package dependencies your project requires to run properly.

In any project using Gulp, it is always a great practice to create this file ahead of time so that you can easily populate your dependency list as you are installing packages or plugins.

To create the package.json file, we will need to run npm's built-in init action using the following command:

npm init

Now, using the preceding command, the terminal will show the following output:

Your command line will prompt you several times, asking for basic information about the project, such as the project name, author, and version number. You can accept the defaults for these fields by simply pressing the Enter key at each prompt. Most of this information is used primarily on the npm website if a developer decides to publish a Node.js package. For our purposes, we will just use it to initialize the file so that we can properly add our dependencies as we move forward. The screenshot for the preceding command is as follows:

Installing Gulp

With npm installed and our package.json file created, we are now ready to begin installing Node.js packages. The first and most important package we will install is none other than Gulp itself.

Locating Gulp

Locating and gathering information about Node.js packages is very simple, thanks to the npm registry. The npm registry is a companion website that keeps track of all the published Node.js modules, including gulp and gulp plugins. You can find this registry at http://npmjs.org. Take a moment to visit the npm registry and do a quick search for gulp.

The listing page for each Node.js module will give you detailed information on each project, including the author, version number, and dependencies. Additionally, it also features a small snippet of command-line code that you can use to install the package, along with readme information that will outline basic usage of the package and other useful information.

Installing gulp locally

Before we install gulp, make sure you are in your project's root directory, gulp-book, using the cd and ls commands you learned earlier. If you ever need to brush up on any of the standard commands, feel free to take a moment to step back and review as we progress through the book.

To install packages with npm, we will follow a similar pattern to the ones we've used previously. Since we will be covering both versions 3.x and 4.x in this book, we'll demonstrate installing both:

To install Gulp 3.x, you can use the following:

npm install --save-dev gulp

To install Gulp 4.x, you can use the following:

npm install --save-dev gulpjs/gulp#4.0

This command is quite different from the 3.x command, because this command is installing the latest development release directly from GitHub. Since the 4.x version is still being actively developed, this is the only way to install it at the time of writing this book. Once released, you will be able to run the previous command without installing from GitHub.

Upon executing the command, it will result in output similar to the following:

To break this down, let's examine each piece of this command to better understand how npm works:

  • npm: This is the application we are running.
  • install: This is the action that we want the program to run. In this case, we are instructing npm to install something in our local folder.
  • --save-dev: This is a flag that tells npm to add this module to the dev dependencies list in our package.json file.
  • gulp: This is the package we would like to install.
Additionally, npm has a –-save flag, which saves the module to the list of dependencies instead of devDependencies. These dependency lists are used to separate the modules that a project depends on to run and the modules a project depends on when in development. Since we are using gulp to assist us in development, we will always use the --save-dev flag throughout the book.

So, this command will use npm to contact the npm registry, and it will install gulp to our local gulp-book directory. After using this command, you will note that a new folder has been created, which is named node_modules. It is where Node.js and npm store all of the installed packages and dependencies of your project. Take a look at the following screenshot:

Installing gulp-cli globally

For many of the packages that we install, this will be all that is needed. With gulp, we must install a companion module gulp-cli globally so that we can use the gulp command from anywhere in our filesystem. To install gulp-cli globally, use the following command:

npm install -g gulp-cli

In this command, not much has changed compared to the original command where we installed the gulp package locally. We've only added a -g flag to the command, which instructs npm to install the package globally.

On Windows, your console window should be opened under an administrator account in order to install an npm package globally.

At first, this can be a little confusing, and for many packages it won't apply. Similar build systems actually separate these usages into two different packages that must be installed separately; one that is installed globally for command-line use and another installed locally in your project.

Gulp was created so that both of these usages could be combined into a single package and, based on where you install it, it could operate in different ways.

Anatomy of a gulpfile

Before we can begin writing tasks, we should take a look at the anatomy and structure of a gulpfile. Examining the code of a gulpfile will allow us to better understand what is happening as we run our tasks.

Gulp started with four main methods: .task(), .src(), .watch(), and .dest(). The release of version 4.x introduced additional methods such as .series() and .parallel(). In addition to the gulp API methods, each task will also make use of the Node.js .pipe() method. This small list of methods is all that is needed to understand how to begin writing basic tasks. They each represent a specific purpose and will act as the building blocks of our gulpfile.

The task() method

The .task() method is the basic wrapper for which we create our tasks. Its syntax is .task(string, function). It takes two arguments—string value representing the name of the task and a function that will contain the code you wish to execute upon running that task.

The src() method

The .src() method is our input or how we gain access to the source files that we plan on modifying. It accepts either a single glob string or an array of glob strings as an argument. Globs are a pattern that we can use to make our paths more dynamic. When using globs, we can match an entire set of files with a single string using wildcard characters as opposed to listing them all separately. The syntax is for this method is .src(string || array)

The watch() method

The .watch() method is used to specifically look for changes in our files. This
will allow us to keep gulp running as we code so that we don't need to rerun
gulp any time we need to process our tasks. This syntax is different between the 3.x and 4.x version.

For version 3.x, the syntax is—.watch(string || array, array), with the first argument being our paths/globs to watch and the second argument being the array of task names that need to be run when those files change.

For version 4.x, the syntax has changed a bit to allow for two new methods that provide more explicit control of the order in which tasks are executed. When using 4.x, instead of passing in an array as the second argument, we will use either the .series() or .parallel() method like so—.watch(string || array, gulp.series() || gulp.parallel()).

The dest() method

The dest() method is used to set the output destination of your processed file. Most often, this will be used to output our data into a build or dist folder that will be either shared as a library or accessed by your application. The syntax for this method is .dest(string).

The pipe() method

The .pipe() method will allow us to pipe together smaller single-purpose plugins or applications into a pipechain. This is what gives us full control of the order in which we would need to process our files. The syntax for this method is .pipe(function).

The parallel() and series() methods

The parallel and series methods were added in version 4.x as a way to easily control whether your tasks are run together all at once or in a sequence one after the other. This is important if one of your tasks requires that other tasks complete before it can be run successfully. When using these methods, the arguments will be the string names of your tasks, separated by a comma. The syntax for these methods is—.series(tasks) and .parallel(tasks).

Understanding these methods will take you far, as these are the core elements of building your tasks. Next, we will need to put these methods together and explain how they all interact with one another to create a gulp task.

Including modules/plugins

When writing a gulpfile, you will always start by including the modules or plugins you are going to use in your tasks. These can be both gulp plugins and Node.js modules, based on what your needs are. Gulp plugins are small Node.js applications built for use inside of gulp to provide a single-purpose action, and can be chained together to create complex operations for your data. Node.js modules serve a broader purpose and can be used with gulp or independently.

Next, we can open our gulpfile.js file and add the following code:

    // Load Node Modules/Plugins
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');

The gulpfile.js file will look as shown in the following screenshot:

In this code, we have included gulp and two gulp plugins: gulp-concat and gulp-uglify. As you can now see, including a plugin into your gulpfile is quite easy. After we install each module or plugin using npm, you simply use Node.js' require() function and pass it in the name of the module. You then assign it to a new variable so that you can use it throughout your gulpfile.

This is Node.js' way of handling modularity, and because a gulpfile is essentially a small Node.js application, it adopts this practice as well.

Writing a task

All tasks in gulp share a common structure. Having reviewed the five methods at the beginning of this section, you will already be familiar with most of it. Some tasks might end up being larger than others, but they still follow the same pattern. To better illustrate how they work, let's examine a bare skeleton of a task. This skeleton is the basic bone structure of each task we will be creating. Studying this structure will make it incredibly simple to understand how parts of gulp work together to create a task. An example of a sample task is as follows:

    gulp.task(name, function() {
return gulp.src(path)
.pipe(plugin)
.pipe(plugin)
.pipe(gulp.dest(path));
});

In the first line, we use the new gulp variable that we created a moment ago and access the .task() method. This creates a new task in our gulpfile. As you learned earlier, the task method accepts two arguments: a task name as a string and a callback function that will contain the actions we wish to run when this task is executed.

Inside the callback function, we reference the gulp variable once more and then use the .src() method to provide the input to our task. As you learned earlier, the source method accepts a path or an array of paths to the files that we wish to process.

Next, we have a series of three .pipe() methods. In each of these pipe methods, we will specify which plugin we would like to use. This grouping of pipes is what we call our pipechain.

The data that we have provided gulp with in our source method will flow through our pipechain to be modified by each piped plugin that it passes through. The order of the pipe methods is entirely up to you. This gives you a great deal of control over how and when your data is modified.

You may have noticed that the final pipe is a bit different. At the end of our pipechain, we have to tell gulp to move our modified file somewhere. This is where the .dest() method comes into play. As we mentioned earlier, the destination method accepts a path that sets the destination of the processed file as it reaches the end of our pipechain. If .src() is our input, then .dest() is our output.

Reflection

To wrap up, take a moment to look at a finished gulpfile and reflect on the information that we just covered. This is the completed gulpfile that we will be creating from scratch in the next chapter, so don't worry if you still feel lost. This is just an opportunity to recognize the patterns and syntaxes that we have been studying so far.

In the next chapter, we will begin creating this file step by step:

    // Load Node Modules/Plugins
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');

// Process Styles
gulp.task('styles', function() {
return gulp.src('css/*.css')
.pipe(concat('all.css'))
.pipe(gulp.dest('dist/'));
});

// Process Scripts
gulp.task('scripts', function() {
return gulp.src('js/*.js')
.pipe(concat('all.js'))
.pipe(uglify())
.pipe(gulp.dest('dist/'));
});

// Watch Files For Changes
gulp.task('watch', function() {
gulp.watch('css/*.css', 'styles');
gulp.watch('js/*.js', 'scripts');
});

// Default Task
gulp.task('default', gulp.parallel('styles', 'scripts', 'watch'));

The gulpfile.js file will look as follows:

Summary

In this chapter, you installed Node.js, learned the basics of how to use npm, and understood how and why to install gulp both locally and globally. We also covered some of the core differences between the 3.x and 4.x versions of gulp and how they will affect your gulpfiles as we move forward.

To wrap up the chapter, we took a small glimpse into the anatomy of a gulpfile to prepare us for writing our own gulpfiles from scratch in the next chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset