Setting Up The Rig

0
83
15 min read

In this article by Vinci Rufus, the author of the book AngularJS Web Application Development Blueprints, we will see the process of setting up various tools required to start building AngularJS apps. I’m sure you would have heard the saying, “A tool man is known by the tools he keeps.” OK fine, I just made that up, but that’s actually true, especially when it comes to programming. Sure you can build complete and fully functional AngularJS apps just using a simple text editor and a browser, but if you want to work like a ninja, then make sure that you start using some of these tools as a part of your development workflow.

Do note that these tools are not mandatory to build AngularJS apps. Their use is recommended mainly to help improve the productivity.

In this article, we will see how to set up and use the following productivity tools:

  • Node.js
  • Grunt
  • Yeoman
  • Karma
  • Protractor

Since most of us are running a Mac, Windows, Ubuntu, or another flavor of the Linux operating system, we’ll be covering the deployment steps common for all of them.

(For more resources related to this topic, see here.)

Setting up Node.js

Depending on your technology stack, I strongly recommend you have either Ruby or Node.js installed.

In case of AngularJS, most of the productivity tools or plugins are available as Node Package Manager (npm), and, hence, we will be setting up Node.js along with npm. Node.js is an open source JavaScript-based platform that uses an event-based Input/output model, making it lightweight and fast.

Let us head over to www.nodejs.org and install Node.js. Choose the right version as per your operating system.

The current version of Node.js at the time of writing this article is v0.10.x which comes with npm built in, making it a breeze to set up Node.js and npm.

Node.js doesn’t come with a Graphical User Interface (GUI), so to use Node.js, you will need to open up your terminal and start firing some commands. Now would also be a good time to brush up on your DOS and Unix/Linux commands.

After installing Node.js, the first thing you’d want to check is to see if Node.js has been installed correctly.

So, let us open up the terminal and write the following command:

node –-version

This should output the version number of Node.js that’s installed on your system. The next would be to see what version of npm we have installed. The command for that would be as follows:

npm –-version

This will tell you the version number for your npm.

Creating a simple Node.js web server with ExpressJS

For basic, simple AngularJS apps, you don’t really need a web server. You can simply open the HTML files from your filesystem and they would work just fine. However, as you start building complex applications where you are passing data in JSON, web services, or using a Content Delivery Network (CDN), you would find the need to use a web server.

The good thing about AngularJS apps is that they could work within any web server, so if you already have IIS, Apache, Nginx, or any other web server running on your development environment, you can simply run your AngularJS project from within the web root folder.

In case you don’t have a web server and are looking for a lightweight web server, then let us set one up using Node.js and ExpressJS.

One could write the entire web server in pure Node.js; however, ExpressJS provides a nice layer of abstraction on top of Node.js so that you can just work with the ExpressJS APIs and don’t have to worry about the low-level calls.

So, let’s first install the ExpressJS module for Node.js.

Open up your terminal and fire the following command:

npm install -g express-generator

This will globally install ExpressJS. Omit the –g to install ExpressJS locally in the current folder.

When installing ExpressJS globally on Linux or Mac, you will need to run it via sudo as follows:

sudo npm install –g express-generator

This will let npm have the necessary permissions to write to the protected local folder under the user. The next step is to create an ExpressJS app; let us call it my-server. Type the following command in the terminal and hit enter:

express my-server

You’ll see something like this:

create : my-server
   create : my-server/package.json
   create : my-server/app.js
   create : my-server/public
   create : my-server/public/javascripts
   create : my-server/public/images
   create : my-server/public/stylesheets
   create : my-server/public/stylesheets/style.css
   create : my-server/routes
   create : my-server/routes/index.js
   create : my-server/routes/user.js
   create : my-server/views
   create : my-server/views/layout.jade
   create : my-server/views/index.jade

   install dependencies:
     $ cd my-server && npm install

   run the app:
     $ DEBUG=my-server ./bin/www

This will create a folder called my-server and put in a bunch of files inside the folder.

The package.json file is created, which contains the skeleton of your app. Open it and ensure the name says my-server; also, note the dependencies listed.

Now, to install ExpressJS along with the dependencies, first change into the my-server directory and run the following command in the terminal:

cd my-server
npm install

Now, in the terminal, type in the following command:

npm start

Open your browser and type http://localhost:3000 in the address bar. You’ll get a nice ExpressJS welcome message. Now to test our Address Book App, we will copy our index.html, scripts.js, and styles.css into the public folder located within my-server.

I’m not copying the angular.js file because we’ll use the CDN version of the AngularJS library.

Open up the index.html file and replace the following code:

<script src= "angular.min.js" type="text/javascript"> </script>

With the CDN version of AngularJS as follows:

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>

A question might arise, as to what if the CDN is unreachable. In such cases, we can add a fall back to use a local version of the AngularJS library.

We do this by adding the following script after the CDN link is called:

<script>window.angular || document.write('<script src="lib/angular/angular.min.js"></script>');</script>

Save the file in the browser and enter localhost:3000/index.html. Your Address Book app is now running from a server and taking advantage of Google’s CDN to serve the AngularJS file.

Referencing the files using only // is also called the protocol independent absolute path. This means that the files are requested using the same protocol that is being used to call the parent page. For example, if the page you are loading is via https://, then the CDN link will also be called via HTTPS.

This also means that when using // instead of http:// during development, you will need to run your app from within a server instead of a filesystem.

Setting up Grunt

Grunt is a JavaScript-based task runner. It is primarily used for automating tasks such as running unit tests, concatenating, merging, and minifying JS and CSS files. You can also run shell commands. This makes it super easy to perform server cleanups and deploy code. Essentially, Grunt is to JavaScript what Rake would be to Ruby or Ant/Maven would be to Java.

Installing Grunt-cli

Installing Grunt-cli is slightly different from installing other Node.js modules. We first need to install the Grunt’s Command Line Interface (CLI) by firing the following command in the terminal:

npm install -g grunt-cli

Mac or Linux users can also directly run the following command:

sudo npm install –g grunt-cli

Make sure you have administrative privileges. Use sudo if you are on a Mac or Linux system. If you are on Windows, right-click and open the command prompt with administrative rights. An important thing to note is that installing Grunt-cli doesn’t automatically install Grunt and its dependencies.

Grunt-cli merely invokes the version of Grunt installed along with the Grunt file. While this may seem a little complicated at start, the reason it works this way is so that we can run different versions of Grunt from the same machine. This comes in handy when your project has dependencies on a specific version of Grunt.

Creating the package.json file

To install Grunt first, let’s create a folder called my-project and create a file called package.json with the following content:

{
  "name": "My-Project",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-concat": "~0.4.0",
    "grunt-contrib-uglify": "~0.5.0",
"grunt-shell": "~0.7.0"

  }
}

Save the file. The package.json is where you define the various parameters of your app; for example, the name of your app, the version number, and the list of dependencies needed for the app.

Here we are calling our app My-Project with Version 0.1.0, and listing out the following dependencies that need to be installed as a part of this app:

  • grunt (v0.4.5): This is the main Grunt application
  • grunt-contrib-jshint (v0.10.0): This is used for code analysis
  • grunt-contrib-concat (v0.4.0): This is used to merge two or more files into one
  • grunt-contrib-uglify (v0.5.0): This is used to minify the JS file
  • grunt-shell (v0.7.0): This is the Grunt shell used for running shell commands

Visit http://gruntjs.com/plugins to get a list of all the plugins available for Grunt and also their exact names and version numbers.

You may also choose to create a default package.json file by running the following command and answering the questions:

npm init

Open the package.json file and add the dependencies as mentioned earlier.

Now that we have the package.json file, load the terminal and navigate into the my-project folder. To install Grunt and the modules specified in the file, type in the following command:

npm install --save-dev

You’ll see a series of lines getting printed in the console, let that continue for a while and wait until it returns to the command prompt. Ensure that the last line printed by the previous command ends with OK code 0.

Once Grunt is installed, a quick version check command will ensure that Grunt is installed. The command is as follows:

grunt –-version

There is a possibility that you got a bunch of errors and it ended with a not ok code 0 message. There could be multiple reasons why that would have happened, ranging from errors in your code to a network connection issue or something changing at Grunt’s end due to a new version update.

If grunt –version throws up an error, it means Grunt wasn’t installed properly. To reinstall Grunt, enter the following commands in the terminal:

rm –rf node_modules
npm cache clean
npm install

Windows users may manually delete the node_modules folder from Windows Explorer, before running the cache clean command in the command prompt.

Refer to http://www.gruntjs.com to troubleshoot the problem.

Creating your Grunt tasks

To run our Grunt tasks, we’ll need a JavaScript file. So, let’s copy our scritps.js file and place it into the my-projects folder.

The next step is to create a Grunt file that will list out the tasks that we need Grunt to perform.

For now, we will ask it to do four simple tasks, first check if our JS code is clean using JSHint, then we will merge three JS files into one and then minify the JS file, and finally we will run some shell commands to clean up.

Until Version 0.3, the init command was a part of the Grunt tool and one could create a blank project using grunt-init. With Version 0.4, init is now available as a separate tool called grunt-init and needs to be installed using the npm install –g grunt-init command line. Also note that the structure of the grunt.js file from Version 0.4 onwards is fairly different from the earlier versions you’ve used.

For now, we will resort to creating the Grunt file manually. Refer to the following screenshot:

In the same location as where you have your package.json, create a file called gruntfile.js as shown earlier and type in the following code:

module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
 
 jshint:{
    all:['scripts.js']
 }
     });

    grunt.loadNpmTasks('grunt-contrib-jshint');
// Default task.
grunt.registerTask('default', ['jshint']);
};

To start, we will add only one task which is jshint and specify scripts.js in the list of files that need to be linted. In the next line, we specify grunt-contrib-jshint as the npm task that needs to be loaded. In the last line, we define the jshint as the task to be run when Grunt is running in default mode. Save the file and in the terminal run the following command:

grunt

You would probably get to see the following message in the terminal:

So JSHint is saying that we are missing a semicolon on lines 18 and 24. Oh! Did I mention that JSHint is like your very strict math teacher from high school.

Let’s open up scripts.js and put in those semicolons and rerun Grunt. Now you should get a message in green saying 1 file lint free. Done without errors.

Let’s add some more tasks to Grunt. We’ll now ask it to concatenate and minify a couple of JS files. Since we currently have just one file, let’s go and create two dummy JS files called scripts1.js and scripts2.js.

In scripts1.js we’ll simply write an empty function as follows:

// This is from script 1
function Script1Function(){
   //------//
}

Similarly, in scripts2.js we’ll write the following:

// This is from script 2
function Script2Function(){
   //------//
}

Save these files in the same folder where you have scripts.js.

Grunt tasks to merge and concatenate files

Now, let’s open our Grunt file and add the code for both the tasks—to merge the JS file, and minify them as follows:

module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
 
 jshint:{
    all:['scripts.js']
 },
 concat: {
   dist: {
       src: ['scripts.js', 'scripts1.js','scripts2.js'],
       dest: 'merged.js'
            }
       },
uglify: {
   dist: {
   src: 'merged.js',
   dest: 'build/merged.min.js'
            }
       } 
    });
grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task. grunt.registerTask('default', ['jshint','concat','uglify']); };

As you can see from the preceding code, after the jshint task, we added the concat task. Under the src attribute, we define the files separated by a comma that need to be concatenated. And in the dest attribute, we specify the name of the merged JS file.

It is very important that the files are entered in the same sequence as they need to be merged. If the sequence of the files entered is incorrect, the merged JS file will cause errors in your app.

The uglify task is used to minify the JS file and the structure is very similar to the concat task. We add the merged.js file to the src attribute and in the dest attribute, we will place the merged.min.js file into a folder called build.

Grunt will auto create the build folder.

After defining the tasks, we will load the necessary plugins, namely the grunt-contrib-concat and the grunt-contrib-uglify, and finally we will register the concat and uglify tasks to the default task.

Save the file and run Grunt. And if all goes well, you should see Grunt running these tasks and informing the status of each of the tasks.

If you get the final message saying, Done, without any errors, it means things went well, and this was your lucky day!

If you now open your my-project folder in the file manager, you should see a new file called merged.js. Open it in the text editor and you’ll notice that all the three files have been merged into this. Also, go into the build/merged.min.js file and verify whether the file is minified.

Running shell commands via Grunt

Another really helpful plugin in Grunt is grunt-shell. This allows us to effectively run clean-up activities such as deleting .tmp files and moving files from one folder to another.

Let’s see how to add the shell tasks to our Grunt file. Add the following highlighted piece of code to your Grunt file:

module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
 
 jshint:{
    all:['scripts.js']
 },
 
 concat: {
   dist: {
       src: ['scripts.js', 'scripts1.js','scripts2.js'],
       dest: 'merged.js'
            }
       },

uglify: {
   dist: {
   src: 'merged.js',
   dest: 'build/merged.min.js'
            }
       } ,


shell: {
    multiple: {
        command: [
            'rm -rf merged.js',
            'mkdir deploy',
            'mv build/merged.min.js deploy/merged.min.js'
        ].join('&&')
    }
}
    });

grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-shell');
// Default task.
grunt.registerTask('default', ['jshint','concat','uglify',
'shell'
]); 
};

As you can see from the code we added, we are first deleting the merged.js file, then creating a new folder called deploy and moving our merged.min.js file into it. Windows users would need to use the appropriate DOS commands for deleting and copying the files.

Note that .join(‘&&’) is used when you want Grunt to run multiple shell commands. The next steps are to load the npm tasks and add shell to the default task list. To see Grunt perform all these tasks, run the Grunt command in the terminal.

Once it’s done, open up the filesystem and verify whether Grunt has done what you had asked it to do. Just like we used the preceding four plugins, there are numerous other plugins that you can use with Grunt to automate your tasks.

A point to note is while the default Grunt command will run all the tasks mentioned in the grunt.registerTask statement, if you would need to run a specific task instead of all of them, then you can simply type the following in the command line:

grunt jshint

Alternatively, you can type the following command:

grunt concat

Alternatively, you can type the following command:

grunt ugligy

At times if you’d like to run just two of the three tasks, then you can register them separately as another bundled task in the Grunt file. Open up the gruntfile.js file, and just after the line where you have registered the default task, add the following code:

grunt.registerTask('concat-min', ['concat','uglify']);

This will register a new task called concat-min and will run only the concat and uglify tasks.

In the terminal run the following command:

grunt concat-min

Verify whether Grunt only concatenated and minified the file and didn’t run JSHint or your shell commands.

You can run grunt –help to see a list of all the tasks available in your Grunt file.

LEAVE A REPLY

Please enter your comment!
Please enter your name here