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