Showing posts with label Grunt. Show all posts
Showing posts with label Grunt. Show all posts

Tuesday, February 17, 2015

The Battle Of Build Scripts: Gulp Vs Grunt

I’ve already written about how to get started with Gulp as well as how to get started with Grunt. They both automate our tasks, they both use Node, and they both require you to create tasks and install plugins of some sort. But do you wonder about the difference between the two, or even, which is better?


gulp vs grunt


In this article I’ll focus mainly on the differences between these two projects which may factor into helping you decide which of the two you may deem better for yourself. I will be using some code which may be unfamiliar. If it is, I suggest reading through the two previously published articles before you get started.


More on Hongkiat.com


Speed


The main difference between Gulp and Grunt lies in how they deal with their automation tasks on the inside. Gulp uses Node streams while Grunt uses temp files. Let’s put that into plain English, shall we?


Assume you would like to write SASS code for your project. You would want to compile your SASS code and then perhaps minify it.


Grunt handles this using intermediary files which are disk I/O operations. Your SASS file is compiled and then written to a temporary file. The temporary file is used by the autoprefixer and then the final product is written to the destination file.


Gulp takes care of all this in-memory. Your source SASS file is compiled, the result is passed to the autoprefixer without being written to a file and the destination file is then written out.


Compared to in-memory operations, disk writes are slow which means that Gulp has a big speed advantage (for now). A speed comparison was done by tech.tmw which shows that most tasks are at least twice as fast on Gulp. While this wasn’t a hugely scientific study the tendency is there and I’ve seen the same with my own projects. But how big of an impact is the difference in speed?


Difference In Seconds


For most projects this won’t matter. Most projects are small. When you’re creating a WordPress theme or something similar the number of files you need to work with are well within a reasonable limit. It really doesn’t matter if your stylesheets are compiled in 400ms or 800ms.


Furthermore, most projects can be structured in such a way that some of the most intensive issues can be sidestepped. If you have 50 SASS files you can just as quickly concatenate them while in development, there won’t be a need to autoprefix or minify them. You will not need to optimize images each time you save a project, and so on.


Even when you really need the big guns because you’re pushing your work onto a staging server or when you’re updating a repository, does a built time of 5 seconds or 9 seconds make much of a difference?


To top it all off, Grunt will add support for piping in the upcoming 0.5 release which will speed things up considerably, making this a moot point.


The Community


Grunt has been around a lot longer than Gulp so it has a significant user base. Grunt currently receives about 37,000 downloads a day on average, Gulp gets a bit more than half that, near the 23,000 mark. That being said, Gulp has only been around for a year and a half, making that number respectable to say the least.


Grunt currently has over 4000 plugins while Gulp has more than 1200 plugins. According to Google trends more people search for Grunt related things, there are more forums that deal with it and generally more community support.


Of course Gulp is up and coming which means this is likely to even out in the long run. However, this is a barrier for some developers, especially those working Grunt-based projects.


I would like to point out that the communities for both are extremely nice. As far as I can tell the relationship between the leaders in each community is amazing, and should serve as an example to all. The creator of Gulp actually helped the writer of the speed test comparison improve the timing accuracies which lead to a decrease in time differences. That’s what I call a gentleman!


Code Vs Configuration


Apparently this is the tipping point for many, but to be honest, I can’t see the issue here personally.


The argument goes like this: Gulp is a good example that code over configuration can be a good thing when configuration gets a bit confusing. Other people say that while this is true and Gulp is easier to read, it is more difficult to write because piping can be a bit confusing.


Before I weight in, here’s the same example first in Grunt, then in Gulp:



grunt.initConfig(
sass:
dist:
files: [
src: "dev/*.scss",
dest: ".tmp/styles",
expand: true,
ext: ".css"
]

,
autoprefixer:
dist:
files: [
expand: true,
cwd: ".tmp/styles",
src: ",*/*.css",
dest: "css/styles"
]

,
watch:
styles:
files: ["dev/*.scss"],
tasks: ["sass:dist", "autoprefixer:dist"]


);
grunt.registerTask("default", ["styles", "watch"]);



gulp.task("sass", function ()
gulp.src("dev/*.scss")
.pipe(sass())
.pipe(autoprefixer())
.pipe(gulp.dest("css/styles"));
);
gulp.task("default", function()
gulp.run("sass");
gulp.watch("dev/*.scss", function()
gulp.run("sass");
);
);

My opinion is that it really doesn’t matter. Sure, if you’re used to the first way you may need to spend some time figuring out the second, but this is true vice versa as well. So for me, the “it’s confusing” argument is completely invalid. Any new method you learn is confusing at first, but if you take the time to understand the logic of each, it all evens out.


That said, I personally prefer Gulp’s API because it is cleaner, and it reflects the way I think more closely than Grunt. This is of course completely subjective and is not an issue with Grunt at all, it’s just my personal preference.


How To Choose


I don’t think there’s any question about the fact that both Grunt and Gulp are great tools and have helped people save countless hours of time over the years. Grunt is a bit slower for now, but has a much bigger community. Gulp is faster, has a cleaner API, but is lacking the user base.


I think that the decision will ultimately come down to continuity, available plugins and preference.


(1) If you’ve been using Grunt/Gulp for a while now and you’re happy with it, there’s no reason to switch.


(2) If your project requires plugins which are not provided by Gulp and you’re not prepared to write one yourself, you will need to go with Grunt.


(3) If the above two considerations do not apply to you it will come down to preference. I suggest trying out both and seeing which one sticks with you.


As I said, I chose to use Gulp because I like its cleaner API better but I am perfectly comfortable using Grunt if a project calls for it. What you should not do is read that Mr. Know-it-all said that Gulp is better and accept it. While there are differences, there is no clear winner and both projects can, and will, coexist. Try them out and make up your own mind.


Note: you might also want to consider opinions from users like Keith Cirkel (A Javascript consultant) who advises you to use neither. In his interesting Why we should stop using Grunt & Gulp article, he suggests using npm.


Further Reading


There are many other excellent articles about this topic. I would heartily recommend any of the following for further reading; it never hurts to read what others have to say!



The Battle Of Build Scripts: Gulp Vs Grunt

Monday, February 16, 2015

The Battle Of Build Scripts: Gulp Vs Grunt

I’ve already written about how to get started with Gulp as well as how to get started with Grunt. They both automate our tasks, they both use Node, and they both require you to create tasks and install plugins of some sort. But do you wonder about the difference between the two, or even, which is better?


gulp vs grunt


In this article I’ll focus mainly on the differences between these two projects which may factor into helping you decide which of the two you may deem better for yourself. I will be using some code which may be unfamiliar. If it is, I suggest reading through the two previously published articles before you get started.


More on Hongkiat.com


Speed


The main difference between Gulp and Grunt lies in how they deal with their automation tasks on the inside. Gulp uses Node streams while Grunt uses temp files. Let’s put that into plain English, shall we?


Assume you would like to write SASS code for your project. You would want to compile your SASS code and then perhaps minify it.


Grunt handles this using intermediary files which are disk I/O operations. Your SASS file is compiled and then written to a temporary file. The temporary file is used by the autoprefixer and then the final product is written to the destination file.


Gulp takes care of all this in-memory. Your source SASS file is compiled, the result is passed to the autoprefixer without being written to a file and the destination file is then written out.


Compared to in-memory operations, disk writes are slow which means that Gulp has a big speed advantage (for now). A speed comparison was done by tech.tmw which shows that most tasks are at least twice as fast on Gulp. While this wasn’t a hugely scientific study the tendency is there and I’ve seen the same with my own projects. But how big of an impact is the difference in speed?


Difference In Seconds


For most projects this won’t matter. Most projects are small. When you’re creating a WordPress theme or something similar the number of files you need to work with are well within a reasonable limit. It really doesn’t matter if your stylesheets are compiled in 400ms or 800ms.


Furthermore, most projects can be structured in such a way that some of the most intensive issues can be sidestepped. If you have 50 SASS files you can just as quickly concatenate them while in development, there won’t be a need to autoprefix or minify them. You will not need to optimize images each time you save a project, and so on.


Even when you really need the big guns because you’re pushing your work onto a staging server or when you’re updating a repository, does a built time of 5 seconds or 9 seconds make much of a difference?


To top it all off, Grunt will add support for piping in the upcoming 0.5 release which will speed things up considerably, making this a moot point.


The Community


Grunt has been around a lot longer than Gulp so it has a significant user base. Grunt currently receives about 37,000 downloads a day on average, Gulp gets a bit more than half that, near the 23,000 mark. That being said, Gulp has only been around for a year and a half, making that number respectable to say the least.


Grunt currently has over 4000 plugins while Gulp has more than 1200 plugins. According to Google trends more people search for Grunt related things, there are more forums that deal with it and generally more community support.


Of course Gulp is up and coming which means this is likely to even out in the long run. However, this is a barrier for some developers, especially those working Grunt-based projects.


I would like to point out that the communities for both are extremely nice. As far as I can tell the relationship between the leaders in each community is amazing, and should serve as an example to all. The creator of Gulp actually helped the writer of the speed test comparison improve the timing accuracies which lead to a decrease in time differences. That’s what I call a gentleman!


Code Vs Configuration


Apparently this is the tipping point for many, but to be honest, I can’t see the issue here personally.


The argument goes like this: Gulp is a good example that code over configuration can be a good thing when configuration gets a bit confusing. Other people say that while this is true and Gulp is easier to read, it is more difficult to write because piping can be a bit confusing.


Before I weight in, here’s the same example first in Grunt, then in Gulp:


 grunt.initConfig( sass: dist: files: [ src: "dev/*.scss", dest: ".tmp/styles", expand: true, ext: ".css" ] , autoprefixer: dist: files: [ expand: true, cwd: ".tmp/styles", src: ",*/*.css", dest: "css/styles" ] , watch: styles: files: ["dev/*.scss"], tasks: ["sass:dist", "autoprefixer:dist"] ); grunt.registerTask("default", ["styles", "watch"]); 

 gulp.task("sass", function () gulp.src("dev/*.scss") .pipe(sass()) .pipe(autoprefixer()) .pipe(gulp.dest("css/styles")); ); gulp.task("default", function() gulp.run("sass"); gulp.watch("dev/*.scss", function() gulp.run("sass"); ); ); 

My opinion is that it really doesn’t matter. Sure, if you’re used to the first way you may need to spend some time figuring out the second, but this is true vice versa as well. So for me, the “it’s confusing” argument is completely invalid. Any new method you learn is confusing at first, but if you take the time to understand the logic of each, it all evens out.


That said, I personally prefer Gulp’s API because it is cleaner, and it reflects the way I think more closely than Grunt. This is of course completely subjective and is not an issue with Grunt at all, it’s just my personal preference.


How To Choose


I don’t think there’s any question about the fact that both Grunt and Gulp are great tools and have helped people save countless hours of time over the years. Grunt is a bit slower for now, but has a much bigger community. Gulp is faster, has a cleaner API, but is lacking the user base.


I think that the decision will ultimately come down to continuity, available plugins and preference.


(1) If you’ve been using Grunt/Gulp for a while now and you’re happy with it, there’s no reason to switch.


(2) If your project requires plugins which are not provided by Gulp and you’re not prepared to write one yourself, you will need to go with Grunt.


(3) If the above two considerations do not apply to you it will come down to preference. I suggest trying out both and seeing which one sticks with you.


As I said, I chose to use Gulp because I like its cleaner API better but I am perfectly comfortable using Grunt if a project calls for it. What you should not do is read that Mr. Know-it-all said that Gulp is better and accept it. While there are differences, there is no clear winner and both projects can, and will, coexist. Try them out and make up your own mind.


Note: you might also want to consider opinions from users like Keith Cirkel (A Javascript consultant) who advises you to use neither. In his interesting Why we should stop using Grunt & Gulp article, he suggests using npm.


Further Reading


There are many other excellent articles about this topic. I would heartily recommend any of the following for further reading; it never hurts to read what others have to say!











The Battle Of Build Scripts: Gulp Vs Grunt

Wednesday, February 11, 2015

How To Use Grunt To Automate Your Workflow [Tutorials]

I’m a huge advocate of automation because it makes life that much simpler. Why spend time on menial, monotonous tasks that suck your life-force right out when you have a computer to do things for you? This is especially true for web development.


automate workflow with grunt


Many development tasks can be a chore. While developing you may want to compile code, when pushing a development version you might concatenate and minify files, remove development only resources, and so on. Even relatively uncomplicated ones like deleting a bunch of files, or renaming folders can take up a large chunk of our time.


In this article I’ll show you how you can make your life easier by leveraging the excellent functionality offered by Grunt, a Javascript task runner. I’ll guide you through the whole process so no worries even if you’re not a Javascript wizard!


More on Hongkiat.com:


Installing Grunt


Installing Grunt is pretty easy because it uses the node package manager. This means that you may also have to install Node itself. Open a terminal or a command prompt (I’ll be calling this terminal from now on) and enter nmp -v.


If you see a version number you have npm installed, if you see a "command not found" error, you’ll have to install it by going to the node downloads page and selecting the version you need.


Once Node is installed, getting Grunt is a matter of a single command issued in the terminal:


npm install -g grunt-cli

Basic Usage


You will be using Grunt on a project-to-project basis since each project will have different requirements. Let’s start a project now by creating a folder and navigating to it via our terminal as well.


Two files make up the heart of Grunt: package.json and Gruntfile.js. The package file defines all the third-party dependencies your automation will use, the Gruntfile lets you control how exactly these are used. Let’s create a bare-bones package file now with the following content:



"name": "test-project",
"version": "1.0",
"devDependencies":
"grunt": "~0.4.5",


The name and version is up to you, the dependencies must contain all packages you are using. We’re not doing anything at the moment so we’ll just make sure Grunt itself is added as a dependency.


You may be asking yourself what that squiggly line (~) called a tilde is doing there.


Versions can be required using the rules from the semantic versioner for npm. In a nutshell:


  • You specify an exact version like 4.5.2

  • You can use greater than/less than to indicate minimum or maximum version such as >4.0.3

  • Using the tilde specifies a version block. Using ~1.2 is considered to be 1.2.x, any version above 1.2.0 but below 1.3

A lot more ways of specifying versions is available but this is enough for most needs. The next step is to create a Gruntfile which will perform our automations.



module.exports = function(grunt)

grunt.initConfig(
pkg: grunt.file.readJSON("package.json")
);

grunt.registerTask("default", [] );

;

This is basically the skeleton for a Gruntfile; there are two places of interest. One location is inside the initConfig() function. This is where all your project configuration goes. This will include things like handling LESS/SASS compiling, minifying scripts and so on.


The second location is below that function where you specify tasks. You can see one task specified named “default”. It is empty at the moment so it does nothing, but we’ll expand on that later. Tasks essentially queue up bits and pieces from our project configuration and execute them.


For example, a task named “scripts” may concatenate all our scripts, then minify the resulting file and then move it to its final location. These three actions are all defined in the project configuration but are “pulled together” by the task. If this isn’t clear just yet don’t worry, I’ll be showing you how this is done.


Our First Task


Let’s create a task which minifies a single javascript file for us.


There are four things we need to do any time we want to add a new task:


  • Install a plugin if necessary

  • Require it in the Gruntfile

  • Write a task

  • Add it to a task group if needed

(1) Find And Install Plugin


The easiest way to find the plugin you need is to type something like this into Google: “minify javascript grunt plugin”. The first result should lead you to the grunt-contrib-uglify plugin which is just what we need.


The Github page tells you all you need to know. Installation is a single line in the terminal, here’s what you need to use:



npm install grunt-contrib-uglify --save-dev

You may need to run this with admin priviledges. If you get something like npm ERR! Please try running this command again as root/Administrator. along the way just type sudo before the command and enter your password when prompted:



sudo npm install grunt-contrib-uglify --save-dev

This command actually parses your package.json file and adds it as a dependancy there, you will not need to do that manually.


(2) Require In Gruntfile


The next step is to add in your Gruntfile as a requirement. I like to add plugins at the top of the file, here’s my complete Gruntfile after adding grunt.loadNpmTasks("grunt-contrib-uglify");.



module.exports = function(grunt)

grunt.loadNpmTasks("grunt-contrib-uglify");

grunt.initConfig(
pkg: grunt.file.readJSON("package.json")
);

grunt.registerTask("default", [] );

;

(3) Create a task for minifying scripts


As we discussed, this should be done within the initConfig() function. The Github page for the plugin (and most other plugins) gives you plenty of information and examples. Here’s what I used in my test project.



uglify:
build:
src: "js/scripts.js",
dest: "js/scripts.min.js"



This is pretty straightforward, I specified the scripts.js file in my project’s js directory and the destination for the minified file. There are many ways to specify source files, we’ll take a look at that later.


For now, let’s take a look at the complete Gruntfile after this has been added, to make sure you know how things fit together.



module.exports = function(grunt)

grunt.loadNpmTasks("grunt-contrib-uglify");

grunt.initConfig(
pkg: grunt.file.readJSON("package.json"),

uglify:
build:
src: "scripts.js",
dest: "scripts.min.js"


);

grunt.registerTask("default", [] );

;

(4) Add this configuration to a task group


Right now you could go to your terminal and type grunt uglify but we’ll need task groups to run multiple tasks later on. We have the default task empty, just waiting for something to be added so let’s modify it to the following:



grunt.registerTask("default", ["uglify"] );

At this stage your should be able to go to the terminal, type grunt and see the minification take place. Don’t forget to create a scripts.js file of course!


That didn’t take a lot of time to set up did it? Even if you’re new to all this and it took you some time to work through the steps, the time it saves will surpass time spent on it within a few uses.


Concatenating Files


Let’s look at concatenating files and learn how to specify multiple files as a target along the way.


Concatenation is the process of combining the contents of multiple files into a single file. We’ll need the grunt-contrib-concat plugin. Let’s work through the steps:


To install the plugin use npm install grunt-contrib-concat --save-dev in the terminal. Once done, make sure to add it to your Gruntfile just like before using grunt.loadNpmTasks("grunt-contrib-concat");.


Next up is the configuration. Let’s combine three specific files, the syntax will be familiar.



concat:
dist:
src: ["dev/js/header.js", "dev/js/myplugin.js", "dev/js/footer.js"],
dest: "js/scripts.js",
,
,

The code above takes the three files given as the source and combines them into the file given as the destination.


This is already pretty powerful but what if a new file is added? Do we need to come back here all the time? Of course not, we can specify a whole folder of files to concatenate.



concat:
dist:
src: "dev/js/*.js""],
dest: "js/scripts.js",
,
,

Now, any javascript file within the dev/js folder will be merged into one big file: js/scripts.js, much better!


Now it’s time to create a task so we can actually concatenate some files.



grunt.registerTask("mergejs", ["concat"] );

This is not the default task anymore so we’ll need to type its name in the terminal when we issue the grunt command.



grunt mergejs

Automating Our Automation


We’ve already made a lot of progress but there’s more! For now, when you want to concatenate or minify you need to go to the terminal and type the appropriate command. It’s high time we take a look at the watch command which will do this for us. We’ll also learn how to execute mulitple tasks at once, along the way.


To get going we’ll need to grab grunt-contrib-watch. I’m sure that you can install it and add it to the Gruntfile on yuor own by now, so I’ll start by showing you what I use in my test project.



watch:
scripts:
files: ["dev/js/*.js"],
tasks: ["concat", "uglify"],
,


I named a set of files to watch “scripts”, just so I know what it does. Within this object I have specified files to watch and tasks to run. In the previous concatenation example we pulled together all the files in the dev/js directory.


In the minification example we minified this file. It makes sense to watch the dev/js folder for changes and run these tasks whenever there are any.


As you can see, multiple tasks can be called easily by separating them with commas. They will be performed in sequence, first the concatenation, then the minification in this case. This can also be done with task groups, which is kind of why they exist.


We can now modify our default task:



grunt.registerTask("default", ["concat", "uglify"] );

Now we have two choices. Whenever you want to concatenate and minify your scripts you can switch to the terminal and type grunt. You can also use the watch command to initiate the watching of your files: grunt watch.



It will sit there, waiting for you to modify these files. Once you do, it will perform all tasks assigned to it, go ahead, give it a try.



That’s much better, no input needed from us. You can now work away with your files and everything will be nicely done for you.


Overview


With that rudimentary knowledge of how plugins can be installed and used and how the watch command works, you are all set to become an automation addict yourself. There is a lot more to Grunt than what we discussed but nothing you couldn’t handle on your own.


Using commands for compiling SASS, optimizing images, autoprefixing, and more is just a matter of following the steps we discussed and reading the syntax the plugin requires.


If you know of some particularly great uses for Grunt please let us know in the comments, we’re always interested to hear how you use tools like Grunt!



How To Use Grunt To Automate Your Workflow [Tutorials]