## Setting up gulp First, let's make sure we have `node` and `npm` installed: ```bash $ node -v v0.10.25 $ npm -v 1.3.24 ``` Now let's try to run `gulp`. If everything goes to plan, we should see our first error: ```bash $ gulp command not found: gulp ``` Perfect! Let's ask NPM for a fresh copy of `gulp`: ```bash $ npm install gulp -g ... installing gulp ... ``` This installs `gulp` command-line utility and makes available globally. Now, let's try running `gulp` again: ```bash $ gulp [gulp] No gulpfile found ``` Nice, our first error! `gulp` is telling us that it doesn't have a `gulpfile` with instructions for it to follow. We solve this by simply adding `gulpfile.js` to our directory root: ```bash $ touch gulpfile.js ``` We haven't added any instructions but sipmly having having the file should give us a new error: ```bash $ gulp [gulp] Using gulpfile /Users/chan/code/talks/gulpfile.js [gulp] Task 'default' was not defined in your gulpfile but you tried to run it. [gulp] Please check the documentation for proper gulpfile formatting. ``` Boom! Now we're talking. `gulp` is running and it sees our `gulpfile`. We're on a roll! It tells us that we don't have a `default` task. Every gulpfile needs a `default` task to run, when `gulp` is executed without arguments. We find the syntax for creating a `gulp` task in [their docs](https://github.com/gulpjs/gulp/#sample-gulpfile). Looks like it's `gulp.task('taskName');`. Let's try it: ```bash $ echo "gulp.task('default');" >> gulpfile.js $gulp ... ReferenceError: gulp is not defined ... ``` Yuck! Now we have a **really** ugly error... But don't lose heart. This error looks scarier than it is. `node` is telling us that there is no reference to 'gulp' in our file. We simply need to add a reference to `gulp` in our `gulpfile`: ```bash $ open gulpfile.js ``` [ add the following line to the very top of your `gulpfile` ] ```js // gulpfile.js var gulp = require('gulp'); ``` Now that we've told node what `gulp` means, in our script, lets try running `gulp` again: ```bash $ gulp [gulp] Using gulpfile /Users/chan/code/talks/gulpfile.js [gulp] Starting 'default'... [gulp] Finished 'default' after 71 μs ``` Hurray! We now have a working `gulpfile` that does nothing! Pat yourself on the back firmly. --- ## Adding a process Now, `gulp` just sits on top of `node`. So, we can do anything we could do node: ```javascript // gulpfile.js // update our default task with a function gulp.task('default', function () { console.log('Hello Gulp!') }); ``` Run this and we'll see `Hello Gulp!` amidst the `gulp` output: ```bash $ gulp [gulp] Using gulpfile /Users/chan/code/talks/gulpfile.js [gulp] Starting 'default'... Hello Full Stack [gulp] Finished 'default' after 137 μs ``` This is particularly unuseful. So, let's turn this into something that can compile CoffeeScript into JavaScript. Let's start with a new task for this: `gulp scripts`. We're going to mimic what we did with our `default` task. `gulp` gives great errors. It's easy to start with the process you want and respond to the errers until it works. Let's try `gulp scripts` ```bash $ gulp scripts [gulp] Using gulpfile /Users/chan/code/talks/gulpfile.js [gulp] Task 'scripts' was not defined in your gulpfile but you tried to run it. [gulp] Please check the documentation for proper gulpfile formatting. ``` As I'm sure you expected, this fails. We haven't written a `scripts` task. Let's write it now. [ add this to your `gulpfile` ] ```javascript // gulpfile.js gulp.task('scripts', function () { gulp.src('src/*.coffee').pipe(gulp.dest('./')); }); ``` There's a lot of code we haven't covered here. So take a second to look it over. It may seem jarring at first but give it a second to sink it... Now we can talk about what it's doing. First, we've registered a new `task` named `scripts`. Much like our `default` task, it responds by running a function. That function start by calling `gulp.src()` to collect the files in the path we specify. Here, we're using `*` to say "grab any and all files in the `src` directory. We then use `pipe()` to funnel those files through another process, `gulp.dest()`. `gulp.dest()` places the files specified with a path. In example, we're using `./` to tell gulp that we want our finished files dumped into the root directory. Notice how easily that reads? If you've been using JavaScript for a while, this should look painfully obvious. Any ideas what will happen when we run this? ```bash $ gulp scripts ``` [ this section requires some previous setup. Add file `src/fun.coffee` for the examples to work ] Gulp found our `src/fun.coffee` file and processed it by creating a new `fun.coffee` file in the directory root. Great! But this isn't exactly what we want. All we've done is duplicate our file in the directory root. We need to process the CoffeScript file **before** placing it in the destination path. We can accomplish this by chaining another `pipe()` right between `gulp.src()` and `.pipe(gulp.dest(...))`. This `pipe` will handle the actual processing of the file. [ update the task to look like this ] ```javascript // gulpfile.js gulp.task('scripts', function () { gulp.src('src/*.coffee') .pipe(coffee()) .pipe(gulp.dest('./')); }); ``` Now, when we run this, you shold have a pretty good idea what's going to happen: ```bash $ gulp scripts [gulp] Using gulpfile /Users/chan/code/talks/gulpfile.js [gulp] Starting 'scripts'... [gulp] 'scripts' errored after 5.17 ms coffee is not defined ``` That's right. Another error! You'll notice that gulp is getting smarter and our errors are less scary. `gulp` tells us that we have another reference error. We need a `coffee` processor. Let's add the reference to our `gulpfile`: ```javascript // gulpfile var coffee = require('gulp-coffee'); ``` Now it should work, right?! ```bash $ gulp scripts Error: Cannot find module 'gulp-coffee' ``` AHHH! Our error is getting uglier! We have our reference but `node` can't find `gulp-coffee`. To add it. We turn back to our trusty package manager, NPM. ```bash $ npm install gulp-coffee ... installing gulp-coffee ... ``` And now, running `gulp scripts`, we should get a `fun.js` file placed in our root directory: ```bash $ gulp scripts $ ls fun.js gulpfile.js src ``` "And there was much reqoicing." --- ## If there is time... It's worth pointing out that this isn't any better than using the `coffee` cli. If we have to run the `gulp` command each time we change our file, howe does gulp help us? We need a way to watch the file system. And `gulp.watch()` helps us with exactly that. Like `gulp.task()`, `gulp.watch()` can take a path as it's first argument and a function as its second. But when we watch a directory, we may want to run a number of tasks! `gulp` accounts for this by allowing you to send an array of task names as the second argument. Let's create a new task `watch` to play with this: ```javascript // gulpfile.js gulp.task('watch', function () { gulp.watch('src/*.coffee', ['scripts']); }); ``` Now, running `gulp watch` will continuously watch our file system for changes: ``` $ gulp watch ``` [ make changes to `src/fun.coffee` ] Play around with `src/fun.coffee` and see our `watch` task respond in the terminal. ```coffeescript // fun.coffee console.log 'Hello Gulp!' ``` You can see that `gulp` is keeping an open process to re-run our task each time `fun.coffee` is changed. AWESOME! --- ## Changing the `default` task Sadly, we only have one task. It'd be nice to have that be our `default` wouldn't it? Running `gulp` without arguments would save us a lot of finger fatigue. Let's update our `default` task to run `scripts` and `watch` when `gulp` is run without arguments. ```javascript // gulpfile.js gulp.task('default', ['scripts', 'watch']); ``` ```bash $ gulp ``` :) ## outro As you can see, Gulp.js is insanely flexible, has very little configuration, and writes like application code. I think you'll really like using it in your projects. Who has questions?