Enough Node for Building a Simple Website

In the last post we covered creating and running scripts from a command line . In this post we will discuss how to create a basic website. We will also start using Node’s package manager called NPM.

The Most Basic Server Ever

Let’s create the most basic Node webserver we can. Start by creating a new JavaScript file called server.js. All you need to create a basic webserver is the following:


var http = require('http');
 
var server = http.createServer(function(req, res) {
    res.writeHead(200);
    res.write('<p>Hello world!</p>');
    res.end();
});
 
var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

If you look at the spacing, you can see that this very minimal code can be broken up into three pieces. The first is the import of the http module. This is one of the built-in modules for Node, like the module we used in the last post for file system access. The http module is used for doing activities related to HTTP as you might have guessed. One of those activities can be to create a server.

The next section actually creates the server. Though functional, this server always returns the same response, a 200 HTTP status code (which means the request was OK) and a short string of HTML.

The third section actually gets the server object to start listening for connections on port 10001 (this is not a special port and was just chosen at random).

If you run this file (by typing node server in a terminal window, just as you would run a script as we did in the last tutorial), you can open your web browser and go to http://localhost:10001/ to view the fantastic server that you created. Congratulations, you have made a website with Node. Unfortunately it isn’t a very capable website, so we need to improve things.

Getting Started with NPM

Though creating your own web framework is obviously possible with Node, we will take the easy route and use a pre-made web framework to make this easier. To do this, we need to use NPM (Node Package Manager) to get our web framework for us since Node doesn’t ship with one out-of-the-box.

The first thing to do is to go to the root of your Node website in a Terminal/Command Prompt and type npm init. The NPM process will ask you a series of questions and create a package.json file for your project. If you don’t know the answer to a question, just hit enter. It will put something in for you. This is a sample package.json file. Obviously your answers will make your file look different. But what is in it at this point is not all that important (we will explore the package.json file more in a later post). The important thing is how we will use it in just a bit.


{
  "name": "whatever",
  "version": "1.0.0",
  "description": "This is so cool",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "Eric Sowell",
  "license": "ISC"
}

The web framework we will use is called Express. All we need to do to install express is to enter the following into your terminal window.

npm install express

Executing that will download the express framework into a sub-folder called node_modules. If the project is under source control, you will want to avoid checking in the node_modules folder as it will add the source of every library that you use to your source repository. This is technically fine but not ideal and probably for obvious reasons. Instead, you should ignore that directory. If you are using git, add the directory to your .gitignore file.

But this then creates another problem. If a coworker needs to work on your project and downloads the code, how will he know to install express so he can run your code? Sure, he can look in all the files and figure out what to install but there is a better way. Instead of the above command to install express, use this one:

npm install express --save

If you open up the package.json file again, you will notice a change.


{
  "name": "whatever",
  "version": "1.0.0",
  "description": "This is so cool",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "Eric Sowell",
  "license": "ISC",
"dependencies": {
    "express": "^4.4.3"
  }
}

The --save parameter will save the library you are installing and the version so that all you or anyone has to do to run the website is do the following.

npm install

This command will look at the dependencies listed in the package.json file and install them. Nifty. That’s enough NPM for now.

Using Express to Server Static Files

Let’s start building our super cool website. To create our first functional website with express, this is all the Node code that we will need. Paste this into the server.js file we created earlier and start the server.


var express = require('express');
 
var server = express();
server.use(express.static(__dirname + '/public'));
 
var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

The first and last sections are either very similar or identical to the last version of the server.js file. The only remarkable section is the middle. First of all, the express module is used to create the server. We are no longer using http.createServer directly as we did before. The next line gets us easy static file serving functionality. How? It’s time to cover yet another topic, middleware.

The Concept of Middleware

I want to dig into what server.use is doing. This function is used to hook up middleware. The concept of middleware isn’t unique to Node. I first heard of this idea in relation to Rack in the Ruby world. The idea is even taking hold in the .NET world with OWIN. If a web framework supports middleware it means that you can plug in functionality generically. By “plug in” I mean that a framework has an existing pipeline of functionality that it has that you stick something into. In the case of Express, we are plugging into the pipeline for handling requests. By “generically” I mean that you could write a middleware function that has nothing specifically to do with the framework you are using. So I could write a function that takes no dependencies on Express at all and reuse it elsewhere. To show this in action, let’s take the common example logging.


var express = require('express');
var server = express();
 
server.use(function(req, res, next) {
    console.log(req.url);
    next();
});
 
var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

We have defined a piece of middleware that logs the url to the console. The next function is called when this piece of middleware is finished because there can be multiple pieces of middleware, all chained together. Here is a totally contrived example of doing that.


var express = require('express');
var server = express();
 

server.use(function(req, res, next) {
    req.url += 'better'
    next();
});

 
server.use(function(req, res, next) {
    console.log(req.url);
    next();
});
 
var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

This new piece of middleware makes every URL better by appending better to the end of it. If you run this and navigate to http://localhost:10001/steakis, the url /steakisbetter will be written to the console. Though you would never want to do this specifically, if you have been doing web development you have probably wanted to do pre-processing on a request to log data, gather data, do some custom authentication...whatever. Middleware in a flexible way of doing that kind of thing. It allows you to plug in functionality. Now let’s go back to our static file server.


var express = require('express');
 
var server = express();
server.use(express.static(__dirname + '/public'));
 
var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

The line server.use(express.static(__dirname + '/public')); basically says “Alright server, use this Express static middleware that I am telling to look in a folder called ‘public’ for static files, which will be in the directory that this current script is running.” The __dirname variable will be the directory that the file is running in. It then appends /public to tell the server to look in the public directory for files.

So if that is the case, then we should be able to create a directory called public in the same folder as our server.js file and then put in a sample HTML file (let’s say foo.html) and go to http://localhost:10001/foo.html and that file will be returned. Well, if you do that, then yes you will in fact see foo.html returned to you. Yay. This also means that you can put other static files like JavaScript and CSS files into that directory and those will get served up to. So this is all you need to create a static file server.

This piece of middleware also comes with the convention that it will load a file named index.html if the root of the website is accessed. Handy.

Next

So that is how you would create a very simple website that serves up static files. There are a few obvious next steps. We obviously need to serve dynamically generated pages. We should also discuss how to make endpoints for AJAX calls, or maybe even endpoints callable by mobile devices so you could build an API. We will get to both of those. And at some point we will want to hook this up to a data source. First let’s tackle creating dynamic pages. We will then hook it up to some data and start making something more complicated.

comments powered by Disqus