Welcome to Node

las-vegas

It’s my pleasure to present “Welcome to Node” to the dotNet user group in Las Vegas on August 29, 2013. Ideally this presentation is equally applicable to any developer approaching Node, though since this audience is coming from .NET, we’ll also discuss similarities and differences between .NET and Node. You can view the slides and download the code that accompany the presentation.

What is Node?

Node is definitely the new, cool, shiny toy, but what sets Node apart from other frameworks and languages? Isn’t this just the next generation’s Ruby? Node is a JavaScript runtime built atop Google V8. It runs on Windows and *nix. It is a blazing fast engine for I/O bound tasks. It is incredibly cool.

What to do with Node?

Node apps tend to fall into one of two categories:

  1. Web-based apps
  2. Command-line tools

Because Node can easily run JavaScript files, it becomes trivial to automate simple tasks by calling node.exe. In many instances, a command-line node utility is much simpler and more concise than a comparable batch file. Once we get into network throughput, Node excels at serving static and dynamic web content, sockets, and even natively supports web sockets. In fact much of Node’s initial popularity is due to the web socket library Socket.io.

A single language for client and server

One of the panacea ideas we’ve had in web development is a single language for both in-browser, client-side content and server-side, back-end content. Right now we’re polyglot programmers, learning HTML, CSS, JavaScript for the client-end, SQL (or NoSQL) for data storage, and PHP, Ruby, Java, .NET or any of a plethora of other technologies for the server-side code. One of the main purposes of Silverlight was to create a single language for in-browser and server-side code to simplify the development experience. Sadly, the days of browser plugins are over, and Silverlight has fallen victim to the trend. This also is a wonderful simplification of the web though — no longer are we burdened by plugins.

The browser renders only three technologies. All content is in HTML — whether created on-the-fly or at design-time. To make this content pretty, we use CSS. The way we make this content dynamic is through JavaScript. It’s the single source of browser interactivity, and because we all have browsers in our pockets, on our desks, tablets and Smart TVs, JavaScript has become the most popular, most ubiquitous language on the planet.

On the server, we have technology choices, but to keep a single language for both client and server, we choose JavaScript. Node empowers this choice with an incredibly fast, built-in web server. Node has built-in support for http connections, sockets, and web sockets. Building atop this stack with various open-source packages, we can achieve all the power and simplicity of MVC — all from JavaScript.

Ultimately, the choice to use JavaScript in both client and server doesn’t mean we have complete code sharing between client and server. Each environment has different concerns and responsibilities. Putting security client-side is silly since we deploy our source code to the browser. But entity validation is a concern that both browser and server share, and we can now accomplish this with a single solution.

Methodologies of Node

Some standard methodologies of Node are:

  1. Everything is asynchronous, no blocking
  2. It’s just Standard JavaScript
  3. There is no global scope
  4. A rich community of open-source packages

Part of what makes Node so fast at I/O is that everything is asynchronous. Instead of blocking the current thread, we use the standard JavaScript pattern of passing in a callback. When the task is complete, our callback is called, and our program resumes. Because of this, the Node event loop is free to service other requests while our request is waiting. If we’re careful (and lucky), what constrains our application isn’t our code but rather the number of concurrent network requests on the box. (This is a wonderful problem to have.)

The one place where Node diverges from standard JavaScript (though ECMAScript 5 and 6 catch up here) is global scope. It is trivially easy in the browser to pollute the global namespace. Forget to put a var in front of your variable and you’ve made it a global variable. If I create an identically named variable in my library and also forget the var then we now share the variable, and very bad things can happen. Node solves this for us by making each file a separate module.

The module system is very powerful in Node. The community of packages (much like NuGet for .NET) empower node developers to orchistrate elegant solutions of common, reusable, replaceable components. We’ll discuss NPM, the Node Package Manager after we install node.

Installing Node

Installing node on Windows or *nix is trivial. Visit http://nodejs.org/, push download, run, next, and done. To prove it installed correctly, open a command prompt or terminal, and type node –version. If it reports a version like v0.10.17, you have Node installed correctly. The really elegant thing is that the Node homepage identifies your OS through your browser and presents the correct download for your OS. I’m browsing from a 64-bit Windows device, so my download is node-v0.10.17-x64.msi. With the Node install, you also installed npm, the Node Package Manager. The installer also recommended you add these to your PATH. As we walk through the demos we’ll presume you have node and npm in your path as well.

The Node REPL

Run node and you start the repl — the read-eval-print loop. You can type standard JavaScript here, and it’ll print the answer.

>2+2
4
>"This is a string"
This is a string
>new Date()
Thu Aug 29 2013 18:00:00 GMT-0700 (US Mountain Standard Time)

The node repl is amazing at quickly running small one-liners, and running node apps is just as easy.

Run a Node app

To run a node app, just pass the JavaScript filename as the first argument.

node app.js

Let’s create a simple hello_world.js file:

console.log(new Date());

and run it:

node hello_world.js

Woo hoo! That was easy. Notice how it started up, did its task, and then exited when it had nothing more to do.

I wrote a batch file a while ago where I was harvesting the current date to use as a folder name. The batch file was a page long. We could modify this one-line program to export the date in a specific format, and call it from the batch file, and save ourselves quite a bit of work. Node is instantly becoming useful.

If we have a task that happens periodically we can create a sample hello_world2.js like this:

setInterval(function () {
    console.log(new Date());
}, 1000);

Run this app the same way:

node hello_world2.js

Note that every second it prints the date, and doesn’t exit. Hit Cntrl-C twice to crash out of this app.

The first scenario is a perfect micro-model for a command-line tool, and the second is a perfect model for a web server. Imagine filling out this file with meaningful content, and just calling it.

Everything is Asynchronous

In Node, there is no Thread.Sleep(). Instead, we use setTimeout(..) to schedule additional work, passing in a callback. If we’re reading a database or an external service, we also just pass in a callback. This is the secret sauce that makes Node so fast. The event loop gets done with the current code having scheduled the future work, and is free to handle other requests. When data is available or when sufficient time has elapsed, the event loop will come back to our request. This one methodology alone makes Node head-and-shoulders faster at processing I/O bound tasks.

Because everything is Asynchronous, Node has developed a convention that allows us to call things and harvest results. In most use-cases, the last argument passed in is the callback, and the callback’s first parameter is an error, or null if it didn’t error.

callTheLib('pass','parameters', function (err, results) {
    if (err) {
        throw err; // Bad things happened
    }
    // It worked
});

Most Node libraries and modules use this standard pattern. You’ll likely see this in most programs and modules you use.

Hello Web Server

Let’s create a simple Node web server. Taking a simple example from nodejs.org:

var http = require('http');
var port = process.env.PORT || 1337;
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(port);
console.log('Server running at http://127.0.0.1:'+port+'/');

and save it to a file like hello_web.js then run it in the normal way:

node hello_web.js

As it gets the web server running, it’ll spit out the url to the console (localhost:1337 if you don’t have a PORT environment variable set). Connect your browser to http://localhost:1337/ and you’ll see the reply. Congratulations, you have a Node web server running.

Module Loading

In the “Hello Web Server” we saw an interesting line that loaded the http module: var http = require(‘http’); This loads a built-in package called “http”. Loading other packages is just as easy. If we had a package called ‘lib_name’, we could load it like this:

var lib_instance = require('lib_name');

These modules are loaded using the CommonJS module loading paradigm, which ironically, is synchronous. The browser can’t use this synchronous mechanism as it may need to download things, so in-browser we use an upgraded paradigm: AMD (Asynchronous Module Definition) from libraries such as RequireJS. Though you can use AMD inside node, it seems awkward to put AMD atop CommonJS. Ideally, Node would leverage AMD and we’d have a singular module loading platform for both client and server, but given the existing codebase, this becomes a very unpopular decision. ECMAScript 6’s modules may resolve this in time.

For modules that aren’t built-in, we can download these modules with NPM (Node Package Manager). npm.exe was installed with the Node download, and provided you opted to add node to your path, you also got npm in your path. Thus for external modules, provided you wanted a module named “packagename”, the process is two steps:

  1. npm install packagename from the command line
  2. var lib_instance = require(‘packagename’); inside your code

You now have a reference to this library that you can use to call functions and inspect properties associated with this library. The files are downloaded into the node_modules folder in the project directory. The project may have additional dependencies, and as NPM downloads your chosen library, it will also download these dependencies recursively. Each project has a package.json file that explains among other things both the design-time and run-time dependencies of the module. You would do well to create a package.json file for each app you write. Use npm init to walk through a series of prompts to construct this file.

One of the major benefits of the node ecosystem is the thriving community publishing open-source packages that do interesting things. For most common problems we have, there are probably 100 libraries that already do it. We can then just string together these packages to orchestrate our application.

Hello Express

The “Hello Web Server” example was lovely in proving the simplicity of the Node platform, but ultimately it isn’t that useful to us. We prefer frameworks that do the heavy lifting for us, and ultimately, we prefer a web framework that gives us an MVC experience. Enter Express, an MVC framework for Node.

Express gives us the separation of concerns we’re used to when we build websites, and feels a lot like ASP.NET MVC or Ruby on Rails. Getting started in Express is very easy. From a command-line or terminal:

  1. npm install -g express
  2. express myapp (or choose an appropriate project name)
  3. cd myapp
  4. npm install
  5. node app.js

In step 4, we ran npm install without a package name. This looked through the application’s package.json manifest looking for dependencies and downloaded each one. Once we’ve got the app running on step 5, look in the console to see which port it randomly chose, and hit that with a browser. Welcome to MVC in Node! Thanks Express.

Traversing through the folders we see the usual suspects:

  • controllers
  • routes
  • views

Pop open a few, make changes, restart the server (node app.js) and see your application come to life.

Command-line tools with Node

The other common paradigm is to use Node for command-line tools. JSHint is a command-line tool that lints your JavaScript. Though we don’t have a “compile” step per-se, we do have JSHint, an excellent tool to help us find and resolve common mistakes we make. Grunt is a JavaScript build system, and another excellent example of a command-line tool.

How can we begin leveraging Node today? We definitely have JavaScript and CSS files associated with our chosen server platform — ASP.NET, Java, PHP, etc. We could use Grunt from within that build to run JSHint, CSS Lint, minify, and concatenate these files to improve server speed. From inside MSBuild we can leverage the Exec task to run grunt. Great first wins for very little effort.

Debugging Node Apps

In Visual Studio, we’re used to hitting F5 and then stepping through code with F10. In Chrome Developer Tools, we can similarly set breakpoints in the browser, examine variables, and F10 debug through code. We can accomplish similar line-by-line debugging in Node as well. Two tools make this incredibly easy.

Node Inspector is an open-source tool that wires up Node’s built-in debugger to Google’s Web Developer Tools for a very intriguing debugging experience. The setup is a bit peculiar, but you can view tutorials here and here. I’d describe these steps if I could do a better job than they did. But I’ll just give props to Danny and Erick.

Another option is WebStorm. WebStorm is an IDE for HTML, CSS, and JavaScript written by JetBrains, the makers of Resharper, RubyMine, and IntelliJ IDEA, the template built into the official Android IDE. Unfortunately, WebStorm is not a free product, but the money is very, very well spent.

  1. Start Webstorm
  2. Create New Project
  3. Choose template “Node.js Express App”, enter other parameters, and click ok
  4. Click configure
  5. Open some js files (like app.js or routes/index.js)
  6. Set breakpoints (click in left margin)
  7. Push the bug icon (next to the green “run” triangle)
  8. In the console tab (bottom-left) look at the port
  9. Visit the url in a browser (e.g. http://localhost:3000/)

Like NodeInspector, we now have everything we’re used to in Visual Studio — run-time property inspection, stack traces, F10 line-by-line debugging. Problem solved.

Summary

This was indeed a whirlwind tour through Node, but hopefully even from this simple introduction, you can see the potential power in the platform. If you followed along, you also got to see how incredibly approachable the platform is too. How will you use Node?. Happy coding!

One thought on “Welcome to Node

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>