Node.js and Express from the ground up, followed by going outside
This post will explain, at a level of reasonable detail, in language accessible to beginners, the workings of Node and Express, and how you may use these two technologies to host a server.
Peruse the section titles to see if this article is right for you:
- What is a server?
- What is node?
- Why use node for your server?
- Creating your first node server
- What is express?
- Why use express for your server?
- Creating your first express server
- Now go outside
What is a server?
To my loved ones, I describe a server in the context of her two sisters that, together, comprise the trinity of how websites “work”:
- The client runs on the end-user’s computer and, in layman’s terms, is responsible for rendering the things that the users sees. The buttons, the page layout, the font, the different components. Other things might be done by the client, but they are beyond the scope of this friendly explanation.
- The server runs on some other part of the internet, and handles messages (often called “requests”) from the client, and sending back the appropriate information from the database or other sources. It is responsible for handling those requests, perhaps querying the database for data to return, and then returning it to the client. An example of such a process is written immediately below.
- The database also runs on some other part of the internet, and, not unexpectedly, stores data that the website uses. Data can be extracted from the database by the server querying it.
For example, say you wanted to login to your website. Such a process may be loosely described as:
- User types username and password into the website (i.e. into the client)
- The client takes the information typed into the boxes and sends it to the server with a request to validate the user’s credentials (typically the credentials will be encrypted before being sent, for security)
- The server receives that request from the client, and queries the database for the user credentials to compare them with what was received
- Presuming the credentials are valid, the server sends a response to the client with confirmation, and perhaps some more information that will be used to keep the user logged-in (say, a “cookie” — out of scope for this discussion)
Another condensed example: One navigates to a certain video on Youtube. The client sends a request to the server to return the page’s video, as well as all the suggested videos and comments that should be shown on the page. The server receives that request, queries the database for that information, and then sends it back to the client (note: heavily, heavily simplified explanation)
So, the server acts as a middle-man between the client and the sources of data that “hydrate” your website. As the builder of a server, you will have to anticipate the various things the client will ask for (login confirmation, videos, user data, etc) and program ways to handle those requests and return the appropriate data to the client.
What is node?
The MDN web docs describe node as follows:
Node (or more formally Node.js) is an open-source, cross-platform runtime environment that allows developers to create all kinds of server-side tools and applications in JavaScript.
Even more simply-put, it is an environment that lets you run Javascript outside of a browser. Really, that’s it. Using node, one may run Javascript on their local machine without having to open a web browser, or on any other machine for that matter.
Why use node for your server?
Web developers commonly use Javascript, or Javascript off-shoots like Typescript, when building website clients. The advantage of using Node is to avoid having to learn and use a different langauge for the server.
Even if you do know a common language for writing a server — like PHP, or python — Node offers the advantage of not having to context switch between Javascript and the other langauge while developing both.
Other advantages include a gigantic library of third-party packages that make building and running servers easier (one of which is Express, which will be covered in this tutorial), and (allegedly) very high performance and speed — I say allegedly because I am not qualified to confirm it.
Creating your first node server
Well, I’m convinced. Let’s build a very simple node server, using just the bare-bones essentials.
Open a terminal and create a folder in which we’ll place our files:
mkdir test-node
cd test-node
Now create a file called hello.js
with the following contents:
// Load HTTP module
const http = require("http");// Declare some variables
const hostname = "127.0.0.1";
const port = 8000;
// Create HTTP server
const server = http.createServer(function (req, res) {
// Set the response HTTP header with HTTP status and Content type
res.writeHead(200, { "Content-Type": "text/plain" });
// Send the response body "Hello World"
res.end("Hello World\n");});
// Prints a log once the server starts listening
server.listen(port, hostname, function () {
console.log(`Server running at http://${hostname}:${port}/`);
});
I’m going to skip ahead to get the server running, after which the contents of this file will be explained.
Save the file and go back to the terminal, and type
node hello.js
Now open a new tab in your browser and navigate to 127.0.0.1:8000
or alternatively localhost:8000
. They are synonymous. You should see “Hello World” written on the page.
What you have just done is, from the client (your web browser), sent a request (a simple one, just querying the port for its contents) to the server (running on your machine) which then responded with the text “Hello World”.
You can stop your server by going to the terminal and pressing ctrl + c
Explanation of the hello.js
file:
const http = require("http");
`http` is a built-in node mudle that contains many useful methods and objects for transferring information over the http protocol. We use it to create a server that listens for requests from the client and sends appropriate responses. More information here
const hostname = "127.0.0.1";
const port = 8000;
This IP address and this port are where the server will be hosted. The IP address ( hostname
) is the canonical “local” IP address, allowing you to access this server that is running on your own computer. In production, the IP would be something else.
There are many ports to each IP address. We select 8000 for no reason. When the server is running, you will use the browser to send a request to this port, and this IP address, and the server will receive it. I promise.
const server = http.createServer
We define a server using the http
module’s createServer
method.
http.createServer( function (req, res) {
// Set the response HTTP header with HTTP status and Content type
res.writeHead(200, { "Content-Type": "text/plain" });
// Send the response body "Hello World"
res.end("Hello World\n");} );
The server requires a function with the arguments req
and res
. The function will dictate all the ways that the server will behave — most importantly: how it will handle all the possible requests from the client. req
and res
are aliases for request
and response
, and in fact, you can type any names you like for these two functions — req and res are simply standard practice.
Entering these arguments, you can now refer to them within the function as if they are request and response objects, which have many useful methods associated with them. The req
object contains information that has been sent from the client (i.e. the “request”). You can see what else is in these req
and res
objects by adding the line console.log(req);
at the top of the function, and restarting the server. When you navigate to localhost:8000
you will not a very long print-out in the terminal showing all the different pieces of information that the client sends the server, which you can then use to handle the requests.
Two methods are used, one that writes the header, which tells the browser how to deal with the information that is sent back. We set the type to "text/plain"
so the browser simply shows the response as text
The other instructs the contents of the message and then sends it back to the browser, “ending” the response (?) (triggering the response to be sent back to the browser)
The last part of the file contains this:
server.listen(port, hostname, function () {
console.log(`Server running at http://${hostname}:${port}/`);
});
This instruct the server to start listening on this port of this IP address. When it has started listening, the function will trigger, printing that string to the console. The server.listen
method is what keeps the script running in the terminal window, listening for any requests that are sent its way by the client. You can read more about precisely how that happens here.
Congratulations, you have now created your first server using node. Now we will inspect the Express module, and understand why it is a useful addition to your server setup.
What is express?
Express is “the most popular node web framework” according to the MDN web docs. It is very popular.
Why use express for your server?
Express provides mechanisms that make developing a server much easier. Developers have created packages on top of Express, called “middleware”, which make advanced server operations much easier, including login confirmation, cookies, sessions, security, etc. There is so much middleware, see it all here.
While the server we have above is quite simple, it can be simplified further by using Express, as we will now see
Creating your first express server
We need to install the express module to create an express server. In the same folder, run this command to create a package management file, then install express
npm init -y
npm install express
Now create a new file called app.js
. The name is of no consequence. Fill it with the following contents:
const express = require("express");
const app = express();
const port = 3000;app.get("/", function (req, res) {
res.send("Hello World!");
});app.listen(port, function () {
console.log(`Example app listening on port ${port}!`);
});
As above, the explanation will follow below. To start the server, return to your terminal and enter this command:
node app.js
Now open a browser window and navigate to localhost:3000
. You will see a familiar “Hello World!” message posted.
Explanation of app.js
:
const express = require("express");
const app = express();
const port = 3000;
Instead of the http
module, we now use the express
module, and instantiate an express server (by convention called app
) in the second line.
app.get("/", function (req, res) {
res.send("Hello World!");
});
We want to tell the server what to do when it receives a request from the /
route (meaning, simply the “home” route that is access when a user navigates to localhost:3000
). GET
is the standard http verb for when a user accesses a page. Further reading on verbs available here.
You can change the access route by supplementing "/"
with "/home"
for instance, after which you would need to navigate to localhost:3000/home
to receive the same response.
As with the req
and res
defined in the earlier example, both are treated as objects that have many useful methods attached to them. We simply use the method called send
on the res
object, which instructs the server to send the message within it back to the client.
app.listen(port, function () {
console.log(`Example app listening on port ${port}!`);
});
Finally we instruct the server to listen on the port, as with our previous example.
We have constructed a very simple server using express.
In the next article, I will be converting Javascript-based express server into one written in Typescript. Read-on if interested.
Now go outside
It’s probably nice outside. Go play ball or something