Open UI: Grunt and JSHint

Previously we looked at how Grunt can improve your Open UI development experience, by automatically reloading the browser, every time a source file is changed. This time we take another step, and configure an automated code check using Grunt and JSHint.

Think of how Siebel Tools prevents you from compiling, or checking in poorly constructed eScript. JSHint will do the same (if not better) job of making sure your client side code is free from language errors, and potential problems.


Starting from where we left off in Open UI: Grunt and Livereload, we should have an operational grunt job that reloads our browser. To add JSHint to the mix, we need to modify the package.json file slightly, to include one new line to install this new dependency

{
  "name": "SiebelGrunt",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-contrib-jshint": "^0.10.0"
  }
}


With your command prompt at the directory with this package.json file, type the following command to pull down this module

npm install

Now we need to configure the Grunt build process, to register this new task, and configure it so it only checks changed files.

module.exports = function(grunt) {
     var sJSPath = '../PUBLIC/enu/*/SCRIPTS/**/*.js';
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),      
          jshint: {
               scripts: [sJSPath]
          },

          watch: {
               scripts: {
                    files: [sJSPath],
                    tasks: ['jshint'],

                    options: {
                         nospawn: true,
                         livereload: true
                    },
               }
          }
    });
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-jshint');

     grunt.event.on('watch', function(action, filepath){
          grunt.config(['jshint', 'scripts'], filepath);
     });

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

To explain what I've done, this newly added block registers JSHint, and uses the file path that we defined previously
          jshint: {
               scripts: [sJSPath]
          },

Next, I register the 'jshint' task with the 'watch' task, which will run JSHint every time a file is changed.
                    tasks: ['jshint'],

The only problem with this configuration is that, JSHint has no idea which file was modified under the watch task, so JSHint will run over all 1500+ files under Siebel scripts and lint them all. If this is run without a filter, your command prompt will hang, and after a while it will come back with a window similar to this.



JSHint reports 15K plus errors across all the files under the Siebel scripts folder, but its not all bad, some of the code under Siebel/scripts is 3rd Party which can raise some errors, and the rest will have been through Oracle's own lint process, and then minified before delivery to customers. We should only be concerned with the files that we have control over.

To make JSHint validate a single file, I added the following block.
     grunt.event.on('watch', function(action, filepath){
          grunt.config(['jshint', 'scripts'], filepath);
     });

This configures a listener on the watch event, and passes in the name of the modified file to JSHint. Now we are ready to roll. Fire up the grunt process.

grunt

Switch back to your code editor, open up postload.js, and type in every body's favorite command "asdf"


Watch will automatically fire JSHint, and report back on the errors, with the line number and a description of the problem. Note that we lost our purple background because our script failed to parse.

Alright, now lets fix that bug


We see that JSHint has reported "1 file lint free", and our browser has automatically reloaded in the background with our purple background again. 

JSHint won't make your Siebel developers better web developers. It will only ensure that any code that is written is written with a consistent syntactic style, and that critical language errors are picked during build and unit test, but it will provide you with the coordinates of any errors that is picked up. 

JSHint is a great safety net, but remember its recommendations can be ignored. To enforce this on a broader scale JSHint can be configured to run against the entire code base on a regular basis, and its results can be enforced by a QA process.

In the case above, a small typo caused 12 errors resulting in missing background color, but in other scenarios, these kinds of errors could cause more serious issues, which illustrates the importance of a code quality tool like JSHint.

Hopefully this article has piqued your interest in Client side build automation. Are you using similar tools on your project, or have you adapted a build process that you would like to share with the Siebel community?.

Send in your comments.

Open UI: Grunt with Livereload

With Siebel Open UI development we naturally spend the majority of our time working on the browser. Part of that requires clearing the browser cache, and hitting F5 to reload the browser.

Sometimes we reload the browser, and think afterwards, did I really clear the cache that time? Maybe not... so we the clear cache, and reload the browser again. Seconds later, we spot a typo in our code and the endless cycle continues. Wouldn't it be good if we can focus on writing the code, and let something else clear the cache and reload the browser? 

This is where tools like Grunt can help.

1. Download No Cache

"No Cache" is a Chrome extension that I wrote to automatically clear your browsers cache. It is available for free on the chrome store. There are 1 click solutions out there, but I prefer to have an automatic background process take care of this.

1. Right click on the No Cache icon, and choose "Options"
2. On the "Cache" tab select "Enable for filtered requests"
3. On the "Filters" tab select the input box, type in "start.swe" and click the + icon


This tells No Cache to clear the cache for every request Siebel makes, this should work on the local or thin client. If you use another browser and have your own favorite clear cache plug in, then that will work as well.

2. Install Grunt

Grunt is a JavaScript task runner that we can configure to reload our browser, but first we need to download and install Node.js from this website


Its not necessary to know what Node.js does, just know that it provides us with the environment to run Grunt. Once you've installed Node.js open a command prompt and type the following line to install the grunt command line globally.

npm install -g grunt-cli

Next we need to decide where to put our Grunt configuration. I like to put it under the Siebel/Client folder because I backup the PUBLIC folder, and don't want copies of Grunt and its modules copied along with this backup.

Open a command prompt, cd to your Client folder, and follow the next set of instructions to install and configure grunt on your local machine.

mkdir grunt
cd grunt

Create a new file in the same folder called package.json, with the following contents

{
  "name": "SiebelGrunt",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "^0.6.1"
  }
}

back at the command prompt, type the following command to download the required dependencies defined in the file above

npm install

Next create a new file called Gruntfile.js, with the following contents

module.exports = function(grunt) {
     var sJSPath = '../PUBLIC/enu/*/SCRIPTS/**/*.js';
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
          watch: {
               scripts: {
                    files: [sJSPath],
                    options: {
                         livereload: true
                    },
               }
          }
    });
    grunt.loadNpmTasks('grunt-contrib-watch');
     grunt.registerTask('default', ['watch']);
};

This file is important, so lets run through it line by line

>     var sJSPath = '../PUBLIC/enu/*/SCRIPTS/siebel/custom/**/*.js';

This path specifies the folder and file pattern that Grunt will watch for changes. Essentially we want to watch for any changes to JS files in the Siebel script folders

> watch: {

This line defines a "watch" task, there are other tasks that can be run. Eg code lint/minification/, but I've kept it simple for this example.

> files: [sJSPath],

configure the files to watch using the path statement above

> livereload: true

This option will spawn a background process that will cause your browser it refresh automatically. To Integrate our browser with this background process, there are 3 options as described here


The browser extension is the most suitable method for development, so go ahead and download it with these instructions.

To start it all up, go back to the command prompt and simply type
grunt

To test it out, goto SCRIPTS, open up any JS file like "postload.js", modify it as below, and watch your browser reload magically.



I've presented the bare minimum required to get up and running with Grunt, but once you have that setup, you no doubt want to look into what other things Grunt can do for you.

A good place to start is..