Setting Up Gulp Tasks for the First Time
How To Set Up Gulp Tasks
First and foremost, what is Gulp.js? The simple answer is:
Gulp.js is a Task/Build runner that makes use of pipes for streaming data that needs to be processed.
So, how can Gulp.js help during the development process?
There are many programming languages that have extensions that make it easier or more elegant to develop big projects. This extensions can be more powerful at development time by adding features that were not available in the original language.
Some examples are:
- CoffeeScript => JavaScript
CoffeeScript:
thisIsAFunction = (a, b, c) ->
# Do something
JavaScript:
function thisIsAFunction(a, b, c) {
// Do something
}
- Jade => HTML
Jade:
form
input#id-name.class-name(type='text', placeholder='Something')
HTML:
<form>
<input type='text' id='id-name' class='class-name' placeholder='Something'/>
</form>
- Sass/Less => CSS
Sass:
.some-class {
background-color: $variable-name;
.some-inner-class {
color: $variable-name;
}
}
CSS:
.some-class {
background-color: #444;
}
.some-class > .some-inner-class {
color: #444;
}
This extensions by themselves do nothing... a browser does not understand what CoffeeScript, Jade or Sass are, they have to be compiled into their original languages for the browser to know what you are trying to program.
This is where Gulp.js comes in. There are many plugins that allow you to compile all this extensions into their original language and make it work with a simple line in Terminal.
Setting Gulp.js up the first time can be confusing so in this tutorial I'm going to guide you into running your first tasks to compile CoffeeScript, Jade and Sass into JavaScript, HTML, and CSS.
Requirements
- Node.js (How to install)
- Newest version of Node Package Manager (NPM)
- Gulp.js installed globally
// run to make sure you have the newest version...
npm install -g npm
npm install -g gulp
For this tutorial we're going to create a simple ToDo app with Angular.js app (no database, it will only store items for the current session and will delete them when refreshing...)
This will be the file structure for the project:
- app/
---- js/
-------- main.coffee // will compile to .js
---- css/
-------- main.scss // will compile to .css
---- index.jade // will compile to .html
- gulpfile.js
- package.json
After compiling our files gulp will create a public/ folder that will be holding the newly compiled files.
Let's get started!
Setting up Angular.js in your Jade/HTML
First, let's set up a basic HTML project in Jade
app/index.jade
doctype html
html
head
title 'ToDo App'
body
input.input-form(type='text', placeholder='Add things to do')
This will create a basic HTML file with a title of "ToDo App" with an input form as the content of the website.
Let's add Angular.js to it by using the Angular.js CDN and link to our stylesheet and our javascript files.
app/index.jade
doctype html
html(ng-app='TodoApp')
head
title 'ToDo App'
link(rel='stylesheet', href='css/main.css')
body(ng-controller='TodoAppController')
input.input-form(type='text', placeholder='Add things to do')
button.btn(type='submit') Submit
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js')
script(src='js/main.js')
app/js/main.coffee
angular.module('TodoApp', [])
.controller 'TodoAppController, [ $scope, ($scope) ->
# logic goes here
]
app/css/main.scss
$black: #444;
$gray: #eee;
$danger-red: #d54444;
body {
background-color: $gray;
color: $black
}
That's the base of your app with Angular.js ready to go to create the app using Jade, CoffeeScript and Sass.
The Logic for the App
I'm going to make this app really simple since the idea for this tutorial is not how to create an app but how to compile and run tasks using Gulp.js
app/index.jade
doctype html
html(ng-app='TodoApp')
head
title 'ToDo App'
link(rel='stylesheet', href='css/main.css')
body(ng-controller='TodoAppController')
input.input-form(type='text', placeholder='Add things to do')
button.btn(type='submit') Submit
ul
li(ng-repeat='task in tasksToDo track by $index') {{task}}
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js')
script(src='js/main.js')
app/js/main.coffee
angular.module('TodoApp', [])
.controller 'TodoAppController, [ $scope, ($scope) ->
$scope.tasksToDo = []
$scope.error = false
$scope.addTask = (task) ->
if not task
$scope.error = true
else
$scope.tasksToDo.push(task)
$scope.newTask = ''
$scope.error = false
]
app/css/main.scss
$black: #444;
$gray: #eee;
$white: #fff;
$danger-red: #d54444;
body {
background-color: $white;
color: $black;
text-align: center;
}
input[type='text'] {
background-color: $gray;
padding: 15px;
font-size: 14px;
border-radius: 4px 0 0 4px;
box-shadow: none;
border: none;
}
button {
padding: 15px;
margin-left: -4px;
font-size: 14px;
border-radius: 0 4px 4px 0;
box-shadow: none;
border: none;
background-color: $black;
color: $white;
}
.error-message {
margin: 10px;
color: $danger-red;
}
ul {
list-style: none;
padding: 0;
li {
margin: 5px;
padding: 5px 20px;
border: 1px solid $danger-red;
}
}
We're done with the app!
But wait... the browser doesn't understand any of this! We have to build our gulpfile.js in order to compile this into a language our browser can understand.
Setting Up gulpfile.js
First make sure you run npm install -g gulp
First we have to set up the package.json
file...
package.json
{
"name": "gulp-tutorial",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"author": ""
}
Now on Terminal run the following command:
npm install --save-dev gulp gulp-jade gulp-sass gulp-coffee gulp-load-plugins gulp-util
This will install the following packages into your package.json as a dev dependency
- gulp: The main task runner
- gulp-jade: This will compile your Jade into HTML.
- gulp-sass: This will compile your Sass into CSS.
- gulp-coffee: This will compile your CoffeeScript into JavaScript.
- gulp-load-plugins: This will allow us to use the plugins without requiring all of them.
- gulp-util: This will allow us to console.log errors in a much nicer/pretty way.
Your package.json
should look like this now:
package.json
{
"name": "gulp-tutorial",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"author": "",
"devDependencies": {
"gulp": "^3.9.0",
"gulp-coffee": "^2.3.1",
"gulp-jade": "^1.0.1",
"gulp-load-plugins": "^1.0.0-rc.1",
"gulp-sass": "^2.0.3",
"gulp-util": "^3.0.6"
}
}
Now let's get into our gulpfile.js
To create a task we use the following syntax:
gulp.task('NAME_OF_TASK', function() {
gulp.src(['PATH_TO_SOURCE_FILE'])
.pipe(**INSERT_TASK**)
.pipe(gulp.dest('PATH_TO_DESTINATION');
});
gulpfile.js
// We have to require our dependencies
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
// create a TASK to compile Jade to HTML using gulp-jade
gulp.task('html', function() {
gulp.src(['./app/**/*.jade'])
.pipe($.jade({pretty: true, doctype: 'html'}))
.on('error', $.util.log)
.pipe(gulp.dest('./public/'));
});
// create a TASK to compile CoffeeScript to JavaScript using gulp-coffee
gulp.task('js', function() {
gulp.src(['./app/**/*.coffee'])
.pipe($.coffee({bare: true}))
.on('error', $.util.log)
.pipe(gulp.dest('./public/'));
});
// create a TASK to compile Sass into CSS using gulp-sass
gulp.task('css', function() {
gulp.src(['./app/**/*.scss'])
.pipe($.sass({style: 'expanded'}))
.pipe(gulp.dest('./public/'));
});
// create a TASK to WATCH for changes in your files
// this will "watch" for any changes in your files and rerun gulp if necessary
gulp.task('watch', function() {
gulp.watch(['./app/**/*.jade'], ['html']);
gulp.watch(['./app/**/*.coffee'], ['js']);
gulp.watch(['./app/**/*.scss'], ['css']);
});
// finally, create a TASK that will run all commands when typing "gulp"
// in Terminal
gulp.task('default', ['html', 'js', 'css', 'watch'], function() {});
Your Terminal should have something simiar to the following logs:
[14:09:59] Using gulpfile ~/Developer/codementor/tutorials/Gulp/gulpfile.js
[14:09:59] Starting 'html'...
[14:09:59] Finished 'html' after 176 ms
[14:09:59] Starting 'js'...
[14:10:00] Finished 'js' after 109 ms
[14:10:00] Starting 'css'...
[14:10:00] Finished 'css' after 83 ms
[14:10:00] Starting 'watch'...
[14:10:00] Finished 'watch' after 11 ms
[14:10:00] Starting 'default'...
[14:10:00] Finished 'default' after 2.54 μs
What is happening with every task is that when you run gulp
in terminal, gulp will go to the gulp.src
specified in each task and compiling the specific file. If there is an error it will be logged in Terminal letting you know the problem. If no error, gulp will create a folder called public/
and place the compiled .html
, .js
and .css
in it.
The watch
task will be checking if you make changes to any of your files and if you do it will re-compile them and update the .html
, .js
or .css
.
You may also want to run just an individual task, you may do so by running the following command:
> gulp NAME_OF_TASK
i.e.
> gulp html
Now if you look at your file directory you will see a newly created folder called public/
with all your compiled files in it, now your browser can read this files!
Extra Comments
Gulp is very powerful and it can be used to do much more, for example:
- Concatenate all your files into a single file
- Inject all your JavaScript and CSS files automatically into your HTML
- Livereload your browser when you make any changes to your files.
- Run BrowserSync
- Create files with a command such as
gulp generate:controller FILE_NAME
- Many more!
I uploaded the files to github and you can check it out here
Nice tutorial . very helpful.
Nice tutorial, thanks. For those who prefer Less over Sass use the gulp-less package, see how: http://zinoui.com/blog/task…
To create init version of package.json you can use ‘npm init’ command, which will ask you some information and create the file with it.
Globally installed Gulp is not mandatory. It is needed only if you want use ‘gulp’ command, but you can use Gulp without installing it globally with ‘node node_modules\gulp\bin\gulp.js’ command.
When you create Gulp tasks, it is better to use return in them. Otherwise it may lead to problems with dependencies between task, because Gulp cannot track, when such tasks are finished. So, if Task1 depends on Task2, Task2 doesn’t use return, and you expect that Task1 will be executed only after Task2 is finished, you will get unpredictable behavior.