Grunt, Coffeescript, Sass, and Haml Project

This post builds off of code that was created in the previous post. The complete source code for this blog post is available on github with accompanying demo.

In the last post we created a Gruntfile that ran a web server for developing web applications. That was just the first building block in our rocking web development setup. Now we’re going to introduce modern tools into the development setup. Javascript, CSS, and HTML are fine but over the past 5 years there has been some real innovation in “front-end” web development. CoffeeScript, Sass, and HAML are three excellent technologies that will increase your developer happiness.

If you aren’t familiar with these languages you may be thinking of them only as syntactic sugar. Well, you better sit down, not only do you get syntactic sugar, you get all sorts of other good stuff. CoffeeScript (for loop syntax, trailing conditionals, the “existential” operator (question mark – ?), switch statements, variable hoisting) brings so much to the table. Perhaps the best thing about CoffeeScript is that it actually has the power to make Javascript fun to write… crazy, right?

Sass (mixins, variables, nesting, partials) is almost a must-have for CSS development. Sass has a couple of competitors that are supposed to be quite good; like Less or SCSS. But for our purposes Sass rocks. Haml is primarily syntactic sugar, but it is so sugary delicious that you’ll forget how you wore the < and > of your keyboard.

Both Sass and Haml require Ruby, version greater than or equal to 1.9.1. Type ruby -v from the command line to determine what version of Ruby you have. If you need to upgrade Ruby (ruby -v returned a version less than 1.9.1) then upgrade all the way to 2.1.

Once you have Ruby installed you have to install the sass and haml gems.

gem install sass
gem install haml

Also CoffeeScript requires that the coffee-script compiler is installed npm install -g coffee-script and you’re ready to roll

Let’s get started

First we’re going to change the directory structure to match the convention of more modern web apps. Setup a structure like this:

├── Gruntfile.js
├── README.md
├── app
│   ├── coffeescript
│   └── stylesheets
├── index.html
├── node_modules
├── package.json
└── public

The coffeescript files will go in app/coffeescript and the sass files will go in app/stylesheets. The compiled files will end up the public directory.

Next add the dependencies to your package.json. We’ll start with CoffeeScript. There are different packages for compiling CoffeeScript with Grunt, I like the grunt-contrib projects so we’ll use grunt-contrib-coffee. Add grunt-contrib-clean and grunt-contrib-coffee to your package.json. grunt-contrib-clean is a nice task for cleaning out your assets before building.

package.json
{
"name": "my-first-grunt-app",
"version": "0.1.0",
"repository": {
"type": "git",
"url": "https://github.com/hoitomt/grunt-setup"
},
"dependencies": {},
"devDependencies": {
"grunt": "~0.4.2",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-connect": "~0.6.0",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-coffee": "~0.9.0"
}
}

Run npm install and update Gruntfile.js with the coffee task and watcher:

// Gruntfile.js
module.exports = function(grunt){
grunt.initConfig({
connect: {
server: {
options: {
base: './',
port: '4000',
host: '*'
}
}
},
clean: {
build: {
src: ['public/javascripts', 'public/stylesheets']
}
},
coffee: {
compile: {
options: {
bare: true
},
files: [{
expand: true,
cwd: 'app/coffeescript',
src: ['**/*.coffee', '**/*.js'],
dest: 'public/javascripts',
ext: '.js'
}]
}
},
watch: {
js: {
files: ['app/coffeescript/**/*.coffee'],
tasks: ['coffee']
}
}
});

grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-coffee');

grunt.registerTask('build', ['clean', 'coffee']);
grunt.registerTask('default', ['build', 'connect', 'watch']);
};

This is the entire Gruntfile.js. It’s a lot to look at but I wanted to point out a few things. First a clean task and a coffee task have been added. The clean task will remove all files from the specified directories (public/javascripts and public/stylesheets). The coffee task will compile all files with a .coffee extension in the app/coffeescript directory. It will put the compiled files into the dest directory with the ext extension, in this case it is public/javascripts with the .js extension.

Now create a coffeescript file to make sure everything is working

# app/new_file.coffee
alert 'Starbucks!'

Add your compiled javascript file (soon to be created) to your index.html

<!-- index.html -->


Grunt Setup
<script src="public/javascripts/new_file.js"></script>
<h1>Grunt it</h1>

Run the project now with the grunt command: grunt. You should see some output like the following in your terminal:

Running "clean:build" (clean) task
Cleaning public/javascripts...OK

Running "coffee:compile" (coffee) task

Running "connect:server" (connect) task
Started connect web server on http://localhost:4000

Running "watch" task
Waiting...

When you run grunt, a few things will happen:

  1. The web server starts on port 4000. When you visit the site an alert should display with “Starbucks!”
  2. The coffeescript file will be compiled as a javascript file into public/javascripts
  3. The coffeescript file is being watched for changes. Change the coffeescript file to alert "Dunkin Donuts!". Notice that your terminal log will display a message that your coffee file has been compiled. Reload localhost:4000 and the alert message should be changed to “Dunkin Donuts!”

Pretty cool, right? That’s the general idea with Grunt. Most of the grunt configuration is the same across libraries. Let’s add Sass support next.

package.json
"grunt-contrib-sass": "~0.7.1"

Install the dependencies npm install and update Gruntfile.js

// Gruntfile.js
...
sass: {
dist: {
files: [{
expand: true,
cwd: 'app/stylesheets',
src: ['**/*.scss'],
dest: 'public/stylesheets',
ext: '.css'
}]
}
},
...
styles: {
files: ['app/stylesheets/**/*.scss'],
tasks: ['sass']
}
...
grunt.loadNpmTasks('grunt-contrib-sass');
...
grunt.registerTask('build', ['clean', 'coffee', 'sass']);

Add a test style.scss

style.scss
p {
font-size: 12px;
}
#test {
p {
font-size: 16px;
}
}

Run the grunt command and your stylesheet will compile into public/stylesheets/style.css.

Let’s add haml now. This will require a reorganization of the project. Create an app/views directory to store your haml files. Instead of updating package.json directly, let’s use the npm shortcut for installing and updating package.json at the same time npm install grunt-contrib-haml --save-dev. Notice that grunt-contrib-haml has been added to package.json, very cool!

Now for the Gruntfile.js configuration. This looks very similar to the CoffeeScript configuration and the Sass configuration, that’s by design in Grunt. NOTE the change to the connect options, we want to look in the public directory now, not the root directory

// Gruntfile.js
...
connect: {
server: {
options: {
base: './public',
port: '4000',
host: '*'
}
}
},
...
haml: {
dist: {
files: [{
expand: true,
cwd: 'app/views',
src: ['**/*.haml'],
dest: 'public',
ext: '.html'
}]
}
},
...
haml: {
files: ['app/views/**/*.haml'],
tasks: ['haml']
}
...
grunt.loadNpmTasks('grunt-contrib-haml');
...
grunt.registerTask('build', ['clean', 'coffee', 'sass', 'haml']);
...

Create the index.haml file

# app/views/index.haml
!!! 5
%html
%head
%title= "Grunt Setup"
%link{ :href => "/stylesheets/style.css", :media => "screen", :rel => "stylesheet" }
%script{ :src => "/javascripts/new_file.js" }
%body
%h1 Grunt it Haml Style!

You can delete index.html in your root directory. Once you run grunt there will be an index.html compiled from app/views/index.haml file into the public directory.

Go ahead and fire it up with grunt. If all went according to plan you should see the index.html file in the public directory along with the coffeescript and sass files compiled in the public/javascripts and public/stylesheets directories respectively. Make sure to check the site at http://localhost:4000. Was that totally awesome or what!?

All of the source code for this project is in https://github.com/hoitomt/grunt-watchers and the app is running as a GitHub page at http://hoitomt.github.io/grunt-watchers/public/

Advertisements

Development Environment with Grunt

When developing a web application it is very helpful to run the application on an actual web server. The javascript community has built some really excellent tools in the last 5 years that make it very easy to do just that.

Grunt is “the javascript task runner”. What the heck does that mean? It means that a single command grunt can be used to kick off multiple commands and watchers. This is incredibly helpful when developing “modern” web applications where you may want to use coffeescript and sass instead of javascript and css and run the application on a web server. If you are familiar with Ruby on Rails we are going to create something similar to rails s.

This post will show you how to get started using node.js and Grunt to create an application server for hosting html and css. This post is not going to go over installing node.js. Here is a nice overview if you’re interested. Let’s get started

Grunt

First install Grunt npm install -g grunt-cli. The -g flag tells npm to install grunt globally on your machine. This is cool for Grunt, we want all applications to have access to it.

After installing grunt, create a package.json file and Gruntfile.js file in your application root. The package.json file is used by node.js to install dependencies and the Gruntfile.js a configuration file that tells grunt what to do.

package.json
{
  "name": "my-first-grunt-app",
  "version": "0.1.0",
  "repository": {
    "type": "git",
    "url": "https://github.com/hoitomt/grunt-setup"
  },
  "dependencies": {},
  "devDependencies": {
    "grunt": "~0.4.2"
  }
}
// Gruntfile.js
module.exports = function(grunt){
  grunt.registerTask('default', []);
};

After adding package.json and gruntfile.js run npm install. Notice that a node_modules directory is automatically created. Node installs all of your project’s dependencies in that directory. So far only grunt is installed.

This is the basic setup. All additional dependencies will be added to these two files. Dependencies are specified by adding one line to the package.json file in the devDependencies block, and then update Gruntfile.js with the configuration and runtime information.

First add the web server dependency. We’ll use the grunt-contrib-connect library. We also need to add the grunt-contrib-watch library in order to keep the server running.

package.json
...
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-contrib-connect": "~0.6.0"
  }
...

Run npm install after adding the dependencies, and update Gruntfile.js

// Gruntfile.js
module.exports = function(grunt){
  grunt.initConfig({
    connect: {
      server: {
        options: {
          base: './',
          port: '4000',
          host: '*'
        }
      }
    },
    watch: {

    }
  });

  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['connect', 'watch']);
};

We added a connect task and a watch task to the grunt file. The connect task starts a server on port 4000 and the server will look in the root directory (./) for the html files. Then we told grunt where to find those tasks (loadNpmTasks). Finally we added the connect task and the watch task to the the default command so that when you run grunt it will run those tasks. Add an index.html file to the root directory so that you have something look at when you run the server.

<!-- index.html -->
<!DOCTYPE html>
<html>
    <head>
        <title>Grunt Setup</title>
    </head>
    <body>
        <h1>Grunt it</h1>
    </body>
</html>

Now run grunt and navigate to http://localhost:4000. You should see the index.html file.

This setup makes it simple to add a web server to an application. Future posts will build on this setup to add additional functionality.

(https://github.com/hoitomt/grunt-setup)

Build a Website with Github Pages

Sometimes you just want to set up a quick website and it isn’t feasible to share your localhost. Github pages are a great way to do just that. The following walks you through the setup for a Github page.

Let’s get started:

Create Your Github Page

  1. Log into GitHub and create your GitHub repository.

  2. Give your repository a name and description and then follow the directions for creating your new repository. The github repo for this tutorial will be called gh-data-1

  3. As part of the setup process you will create a local folder for your project, initialize it for git and push it to your GitHub account. When you finish the setup process, there should be a README.md in your GitHub repository

  4. In your local repository, create a new branch called gh-pages. git checkout -b gh-pages

  5. Add an index.html file in your local repository like the one below – just a blank template with a heading

    <h1>My Page</h1>
    
  6. Push the gh-pages branch to your github repo
    git add .
    git commit -m "Create the gh-pages branch and add index.html"
    git push origin gh-pages -u
    
  7. Now you can visit your GitHub Page to view your index.html file. http://hoitomt.github.io/gh-data-1/

That’s all for today. We now have a publicly accessible website for free.