Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Automate Your Fancy Build Streams With Gulp

DZone's Guide to

Automate Your Fancy Build Streams With Gulp

Lots of full stack devs out there underestimate the power of process streaming tools like Gulp. Here, we'll show you how to automate the boring stuff with Gulp like minifying CSS, HTML, and JS, joining multiple JS files into a single one, indenting files, and more.

· Web Dev Zone
Free Resource

Make the transition to Node.js if you are a Java, PHP, Rails or .NET developer with these resources to help jumpstart your Node.js knowledge plus pick up some development tips.  Brought to you in partnership with IBM.

Hello, full-stack developers. If you are not using any build system, then you are losing a lot of productivity.

In many cases, you will be developing your code with an idea of maintainability and optimization. Our JavaScript and other Markup code should be placed in a proper location while serving from a web server. If you never heard about Gulp or Grunt you are unlucky. But if you have, this article will strengthen your knowledge. This topic is quite popular in the front-end development field. But for full-stack developers, not so much. I have seen a lot of them underestimating the power of process streaming tools like Gulp, Grunt, or WebPack.

I recently used Gulp effectively in my work to automate a lot of boring stuff. I hope you can too from now on.

Why We Need a Build System?

In the ice age of front end development, developers used to write code and manually update files wherever it was required. They steadily learned from Google Developer Network and other places about how concatenation and minification of HTML, CSS, and JS can improve the page speeds and hence the customer experience. Even though the page speeds and resource (images) loading times may depend on various factors (DB, Latency, etc), it is your responsibility as a full stack developer to optimize all the sensitive parts of a complex web application. So here, that sensitive part is the browser.

When you serve web resources (HTML, CSS, JS) from a web server (Apache or Nginx), the page speeds mainly bet on bandwidth. If your files are huge (with thousands of lines of code and hundreds of KB), then your website may not fare well. In another scenario, if you are loading too many files, it can also cause a glitch in the user's experience (UX).

What to Do to Improve the Web Experience?

The things we are building here:

  • Minify your files to reduce the size

  • Pack or bundle your files into a single file and serve it

For developers, doing these things manually is a painful task. Luckily, we got a great build stream automation tool like Gulp. We can define any tasks and can ask gulp to execute them.

Seeing Is Believing

Here, I am going to show you a working application of Gulp. I created a project called workspace with two folders in it.

  • src/: where are all source files reside for the project
  • build/: where all minified and concatenated files appear

Before rushing in, we should know what prerequisites are needed for Gulp to work. You should have a working copy of Node and npm on your computer. If you don’t have them follow these guidelines: 

How To Install Node.js on Ubuntu 16.04 | DigitalOcean.

If you are using a Mac OS X machine, you can install node using HomeBrew:

Install Node.js and npm using Homebrew on OS X and macOS

Node uses the V6 engine’s C++ library for its executions. If you have a Google Chrome browser installed on your computer, you already have that library. Otherwise, you can easily download all dependencies for the node. After installing node and NPM, you need to install Gulp using this command.

$ npm install --global gulp-cli

Now my project is the workspace folder.

Here we have a nice folder structure (personal taste). All source files will be in the src/ folder. All the minified files and concatenated files will lie in the build/ folder. index.html can also be minified.

Now in the project folder install Gulp:

$ npm install --save-dev gulp


Now we have Gulp. Next, we should give few instructions to Gulp. We create a Gulp file to do that. It is a JavaScript file with tasks defined in it. Gulp understands those tasks and executes them.

node_modules is created by the above command.

Starting the Optimization

Now, let me add some bare-boned HTML to index.html

<html>  
  <head>     
    <title> 
      The simplest HTML example      
    </title>  
  </head>  
  <body>   
    <h1> 
      This is  an HTML Page 
    </h1>   
  </body>
</html>


This file is just a simple example. But in your project, this file can reach a few thousand lines of markup code. So keeping it original (with spaces & tabs) is not good.

The first good habit is to keep source in src/ folder instead of sprinkling it here and there. So I copy the index.html to src/

$ cp index.html src/


Now I should assign a task to Gulp for minifying this index.html in src/ to the index.html in the project directory. For that, I should create a gulpfile. For supplying minifying logic of HTML, we should install a plugin called “gulp-minify-html”. Gulp is a task definer and executor but you should help Gulp by telling how to minify HTML. This is such a plugin where that logic is already written. You can write your custom logic too.

Now add content to the gulp file.

// gulpfile.js
var gulp = require("gulp");
var minifyHtml = require("gulp-minify-html");
gulp.task("minify-html", function(){
   gulp.src("src/index.html")
   .pipe(minifyHtml())
   .pipe(gulp.dest('.'));
});


In the above gulp file, these actions are defined:

  • Import gulp to create tasks.

  • Import gulp-minify-html to minify the HTML file

  • Create a task called minify-html

What Is Happening Here?

A gulp task inputs two arguments. task_name and function_handler

The task name is used for gulp to identify the task to execute whereas the function handler is the actual execution command list. If you see, we are piping a set of instructions one after the other. The essence of Gulp is in that chaining. Let's write those instructions in plain English:

  • Load source file from given path. Here it is from src/index.html

  • Apply minifyHtml function on that loaded content

  • Output the minified file to index.html in the project root

Now save the file and run this command from project root (i.e Workspace).

$ gulp minify-html


It minifies the HTML from src/index.html and puts it in the project root.

Now if we look at the minified index.html File, it looks like:

<html>
  <head>
  <title>The simplest HTML example</title>
  </head>
  <body>
  <h1>This is an HTML Page</h1>
  </body>
  </html>


We ordered Gulp to do something and it did exactly what we wanted. Similarly, we can minify CSS, minify JS, join JS files into a single one, indent files, and much more.

Here I install necessary plugins to the Gulp for performing the above tasks.

$ npm install --save-dev gulp-minify-html
$ npm install --save-dev gulp-minify-css
$ npm install --save-dev gulp-uglify
$ npm install --save-dev gulp-concat


All these plugins will be saved in your node_modules directory in the project root.

Before minifying web resources(JS, CSS) I will create a few dummy scripts. First a JavaScript file:

// src/js/script1.js
var foo = 10;
console.log("foo is", foo)


Now create another JS file in src/js. These files are simple here but in your project, they may span to many thousands of lines of code.

// src/js/script2.js
var bar = 20;
console.log("bar is", bar);


Create a dummy CSS file in src/css directory

/* src/css/custom.css   */
body {
      background-color: red;
} 

.myDiv {
    margin-left: 10%;
    margin-top: 15%;
}


The directory structure looks like this.

Now, I modify my gulpfile to add imports and tasks for minifying, joining of CSS and JS files.

var gulp = require("gulp");
var minifyHtml = require("gulp-minify-html");
var minifyCss = require("gulp-minify-css");
var uglify = require("gulp-uglify");
var concat = require("gulp-concat");

gulp.task("minify-html", function(){

     gulp.src("src/*.html")
    .pipe(minifyHtml())
    .pipe(gulp.dest('.'));
});

gulp.task("merge-minify-js-css", function(){
      gulp.src("src/js/*.js")
     .pipe(concat("main.min.js"))
     .pipe(uglify())
     .pipe(gulp.dest("build/js"));

      gulp.src("src/css/*.css")
     .pipe(concat("custom.min.css"))
     .pipe(minifyCss())
     .pipe(gulp.dest("build/css"));
});


The above code should be clear for you by now. *.js means for all js files in the directory.

Once again in plain English:

  • Import all necessary functions

  • Create task with subtasks in it

  • One subtask is to Concatenate multiple JS files and minify. Then output main.min.js to build/js

  • Another subtask is to concatenate CSS files into a single one and minify. It also produces a custom.min.css to build/css/

Now, let's save and run this gulpfile with tasks.

Gulp finished both the tasks and now you will be able to see the newly created minified files in the tree.

And minified files looks like:

Since minifying is a process of removing white space characters and new lines, it can reduce the file size to a great extent which in turn boost the web page load speeds.

Can’t I Execute All Tasks in One go?

Yes, you can. For that gulp provides a task called “default”. If you feel like you should execute a list of tasks with a simple command then add these lines to above gulp file.

// append to gulpfile.js
gulp.task("default", ["minify-html", "merge-minify-js-css"]);


Now, you can execute all tasks in one single go with just a gulp command.

$ gulp

Do I Need to Run the Gulp Command Every Time I Change My Source Files?

In order to run the code, you cannot directly edit minified files. Instead, you modify source files then will run gulp command. But it is a pretty simple thing. For every small modification, you need to run gulp. In order to make this process automated, Gulp provides you watchers to your source files. Just run a watcher, then modify the source code. Gulp will take care of building files on the fly whenever changes occurred to watching files.

var gulp = require("gulp");
var minifyHtml = require("gulp-minify-html");
var minifyCss = require("gulp-minify-css");
var uglify = require("gulp-uglify");
var concat = require("gulp-concat");

var paths = {
    scripts: "src/js/*.js",
    styles: "src/css/*.css",
    html: "src/*.html"
}

gulp.task("minify-html", function(){

     gulp.src(paths.html)
    .pipe(minifyHtml())
    .pipe(gulp.dest('.'));
});

gulp.task("merge-minify-js", function(){
      gulp.src(paths.scripts)
     .pipe(concat("main.min.js"))
     .pipe(uglify())
     .pipe(gulp.dest("build/js"));

});

gulp.task("merge-minify-css", function(){
      gulp.src(paths.styles)
     .pipe(concat("custom.min.css"))
     .pipe(minifyCss())
     .pipe(gulp.dest("build/css"));
});

// Rerun the task when a file changes
gulp.task('watch', function() {

  gulp.watch(paths.scripts, ['merge-minify-js']);
  gulp.watch(paths.styles, ['merge-minify-css']);
  gulp.watch(paths.html, ['minify-html']);

});


gulp.task("default", ["watch", "minify-html", "merge-minify-js", "merge-minify-css"]);


Here we fragmented HTML, CSS, and JS tasks. Then started watching those files and attaching a task to a particular directory change.

// Rerun the task when a file changes
gulp.task('watch', function() {

    gulp.watch(paths.scripts, ['merge-minify-js']);
    gulp.watch(paths.styles, ['merge-minify-css']);
    gulp.watch(paths.html, ['minify-html']);
});
// Add watch to the default tasks
gulp.task("default", ["watch", "minify-html", "merge-minify-js", "merge-minify-css"]);


Now, when you run the gulp command, it starts a never ending watcher which sits there and silently looks for changes. When a specific file is changed, it executes the task associated with it.

It means when we modify CSS files, CSS minification task will run automatically. This is really helpful if developers are adding changes continuously and the build is automatically generated.

Other Talking Points

Here we just used Gulp for basic UI tasks. Since it runs on Node, you can give operating system commands and custom utility functions for Gulp. For housekeeping and periodic tasks, watching tasks you can use Gulp. You can also build a work stream for git releases and build files with it.

Anyway, I think now you have a basic idea of what Gulp is and how it boosts your productivity by creating automated build streams from a simple configuration file.

Learn why developers are gravitating towards Node and its ability to retain and leverage the skills of JavaScript developers and the ability to deliver projects faster than other languages can.  Brought to you in partnership with IBM.

Topics:
javascript ,js ,front end ,front end development ,web developement ,programing ,productivity ,gulpjs ,gulp ,web 2.0 development

Published at DZone with permission of Naren Arya. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}