ponyfoo.com

Managing Code Quality in NodeJS

Fix
A relevant ad will be displayed here soon. These ads help pay for my hosting.
Please consider disabling your ad blocker on Pony Foo. These ads help pay for my hosting.
You can support Pony Foo directly through Patreon or via PayPal.

I’ve mentioned CI and static asset management in the past. Now I want to talk about code quality.

This article is mostly a follow up on the CI post. I’ll describe how Grunt helped me change the test and build processes used in this blog’s engine.

Before using Grunt, I didn’t really have a real build process. Sure, git push heroku master triggered a build on their end, but I didn’t control any of it, all I did was node app.js.

Similarly, my Travis-CI hook just made sure there weren’t any conflicts with my npm packages. I could do better.

I’ve started leaning towards making the engine more testable, I figured I had to start somewhere. For me, that first step was to use a task runner.

Grunt: proper Build Process

After spending a few days toying with Grunt, I must say it’s really exciting to use a build tool that just works, rather than get in your way. I learned a couple of interesting things, and even created my very own grunt plugin for assetify.

Grunt runs from the command line, and you should install it globally, using npm install -g grunt-cli. Grunt will look for Gruntfile.js, and run the function exported by that module, passing a helper as an argument.

Here’s a sample listing that does basically the same as the traditional node app.js command used to. Save this as Gruntfile.js:

'use strict';

module.exports = function(grunt) {
    grunt.initConfig({});
    grunt.registerTask('app', function(){
        var done = this.async(),
            app = require('./app.js');

        app.start(done);
    });
};

You should make a very minor change to your app.js, and add app.on('close', done);. This will signal grunt to shut down when the server is closed, rather than as soon as it’s idle.

Now you can grunt app to run your web application using grunt. How cool is that? Fine, it’s not very amusing.

The amusing part is the kind of things Grunt enables you to do, now that it’s set up. You can integrate other stuff you might’ve shied away from because it was too cumbersome to run, or complicated to configure. Grunt solves some of that for you.

grunt-cli-sample.png
grunt-cli-sample.png

I’ll now go over some of the tools I integrated into my build process since I switched to Grunt. I’m not saying Grunt enabled me to use these tools, it just made my life easier.

Lint: Static Code Quality Analysis

JSHint is a In case you don’t know it, JSLint helps catch syntax errors (and coding style issues) in your code. JSHint is highly configurable fork of JSLint, and their documentation explains each option in detail.

You should consider JSHint as your very first unit test. Since JavaScript doesn’t have a formal compiler, a linting tool such as JSHint will have to do.

You can find the GitHub repository to their Grunt plugin here, and the actual sources of JSHint are here.

Here’s how I added it to my Gruntfile.js (displaying only the relevant code):

grunt.initConfig({
    jshint: {
        node: {
            files: {
                src: [
                    'gruntfile.js',
                    'src/**/*.js',
                    '!src/static/**/*.js',
                    'test/spec/**/*.js'
                ]
            },
            options: {
                jshintrc: '.jshintrc'
            }
        },
        browser: {
            files: {
                src: [
                    'src/static/**/*.js',
                    '!src/static/config/*.js',
                    '!src/static/.bin/**/*.js',
                    '!src/static/js/vendor/**/*.js'
                ]
            },
            options: {
                jshintrc: '.jshintrc-browser'
            }
        }
    }
});

grunt.loadNpmTasks('grunt-contrib-jshint');

This brings us to an interesting point about Grunt, which is targets. The node and browser properties are just targets, which means that grunt jshint:node will run JSHint with the first set of options, and grunt jshint:browser will run the second set. grunt jshint will do both in turn.

If you’re not already linting your code, it will take you a few moments to make it comply with a default JSHint configuration, but it will be worth it.

Unit Testing

If you’re looking to get started with Unit Testing in NodeJS I’ll just recommend you to read TDD.JS.

I’ll expand on this topic on a later post, since there’s a lot to write on the topic, particularly on testing a dynamically typed language such as JavaScript, which in my opinion is both harder but more enjoyable (when done right).

Meanwhile, you must look at Superhero.js, which offers a bunch of JavaScript articles, videos, and books you should definitely keep an eye out for!

Again with Static Asset Management

I’ve mentioned in the past how I was building assetify. It hasn’t changed much lately, except for a fingerprinting (as in /all.js?v=2r4c-19by10z) middleware that allows us to set far-future Expires headers. Other than that, I did add a grunt plugin for assetify.

If you’re interested in plugging assetify into your Grunt configuration, you should definitely check out the example repository I’ve set up on GitHub. The Grunt setup on that repository also has JSHint and Jasmine tasks, so it might even be a good starting point for configuring a nice Gruntfile.js

Lastly, remember:

Stand watchful, and continuously assess the quality of your code. These guidelines may make maintaining, refactoring, and developing your application leaner, more straightforward, and less bug-prone. You are the one who’s going to have to stand by them. Incorporate them as a part of your everyday work, and you’ll soon start to reap the benefits.

continuous.gif
continuous.gif
Liked the article? Subscribe below to get an email when new articles come out! Also, follow @ponyfoo on Twitter and @ponyfoo on Facebook.
One-click unsubscribe, anytime. Learn more.

Comments