So you just installed Node.js on your system and want to start a short “Hello world” example that renders a simple HTML page?
You’ll soon find out that Node.js offers a very limited set of features out of the box. Paradoxically this is one of the keys to its success and a reason why developers love it.
Wizardry and Black Magic
For many years I’ve used language after language and framework after framework and learning the frameworks was the hardest part every time. Additionally there seemed to be a trend towards wizardry – just enter some commands in the shell and you get your full fledged ORM layer out of your database scheme. (Did I hear you say “Symfony“?) Apparently it seemed like a good idea to abstract as much logic as possible away from the developer and offer an easy to use interface for all functionality the framework developers considered to be useful. We all know those ‘build your own blog in 5 minutes’ examples. (Did I hear you say “Ruby on Rails“?) Everything looks easy and great – until you try to implement real requirements for real clients.
Yes – it is tempting to think that you can get away by driving down the easy road and relying on generators and big chunks of out of the box features but from my perspective this never works out. The time you saved in the first place will be spent afterwards when you try to figure out why the ORM layer logic hidden deep inside the framework doesn’t let you do a select on a date range.
While building something from scratch would have taken its time but would have been fun, you end up spending your time reading through docs, googling and posting on StackOverflow just to understand code written by someone else.
Back to Craftsmanship
Out of curiosity I tried it anyways and surprisingly working with it felt like a relief.
It does this in a very pragmatic and smart way by offering only basic building blocks like filesystem access, protocol support and cryptology along with some basic utility functions and therefore reading through Node.js docs feels like Zen: Reduced, focused and concise.
I felt like getting back to the essence of programming again. No bells, no whistles.
It’s easy to install Node.js on any platform. If you are on Linux you can simply use your package manager to install the latest nodejs package. For all other operating systems download the binaries from the Node.js website.
After that you can run Node.js applications by typing node <yourapplication.js> (depending on your platform the binary may also be named nodejs).
Here’s a basic “Hello world” example. Run it and open http://localhost:4242 in your browser to see if everything is working.
Modules are an important building block for Node.js applications and a great way to properly separate concerns within an application.
A module exposes its functionality by a global data structure module.exports provided by Node.js. Modules are included and assigned to a variable with require(). The exported functionality is only accessible through this variable which basically means that every module creates a namespace.
Here’s an example of creating a module adder.js and then using it.
Read on here for an in depth blog post on module loading in Node.js.
Meet the Community
Granted – implementing a fully fledged web server when all you have is the basic HTTP commands can be a daunting task. But not relying on complex frameworks does not mean that you have to build everything from scratch.
Npm – the Node Package Manager currently holds more than 140.000(!) packages for various purposes – most of them are maintained on GitHub.
Interestingly many of them adhere to the “Do one thing and do it well” philosophy known from UNIX. The result is a pool of small bits of functionality that can be mixed and composed as needed.
I am still wondering why exactly the Node.js community went in this direction and the reason may be, that the way modules work forces developers to keep things simple.
Modules are installed by entering the projects directory and typing npm install –save <modulename>.
The –save flag tells npm to save this dependency in a package.json file inside the current path. Modules will be installed to a folder called node_modules relative to your current path.
There are also a few larger modules that provide a set of functionality with express being the most popular as it provides http, routing and template rendering functions that most web projects need.
If you ever had to migrate a complex legacy php application to a new server you know that this can get extremely unpleasant because of globally installed extensions and libraries the project relies on.
As stated above, in Node.js all dependencies are registered in package.json and installed into the projects directory structure. Usually there are no dependencies to the environment the application runs on (except the node binary of course) and spinning up a new instance running an app only takes minutes because there is no need to provide a specific server environment. This makes Node.js the platform of choice for projects following the Immutable Infrastructure principle introduced by Chad Fowler in 2013.
Where to go from here
After reading this blog post you should have all the information needed to understand the basic building blocks of a Node.js application.
There are many great learning resources like NodeSchool on the web that will help you to move on from here.
This is the last post about Node.js basics. In my upcoming posts I will show its inner workings and how to increase code insight and quality by monitoring Node.js key metrics with Dynatrace.