News

Rapid app dev with Express.js

Explore the powerful work of dynamic server-side JavaScript applications using Express.js and Node

3

JavaScript: the client-side programming language used to add basic interaction and validation for user interfaces. Most web apps could easily have survived without it, but no longer. JavaScript powers a vast number of websites and UI features and, thanks to libraries such as jQuery cropping up, it is no longer feared half as much as it used to be.

It is also no longer resigned just to sit in the client’s browser. Thanks to Node.js, it can also be used to build and power dynamic and powerful server-side applications – and the Express framework has been developed to help you structure your Node web apps.

In this tutorial we will explore the foundations of the Express framework as we build a functional URL shortener application, complete with data storage thanks to MongoDB. We will look at setting up an application, installing modules and dependencies and generating routes, returning static strings, JSON output and rendering complete populated HTML from dynamic sources.

Package.json

Create a new package.json file in the root of your project directory. As with traditional Node applications, this will hold core information relating to your application, including the dependencies for external Node modules. Let’s add the latest version of Express as a dependency and save the file.

001 {
002 “name”: “express_introduction”,
003 “description”: “Express application”,
004 “version”: “0.0.1”,
005 “private”: true,
006 “scripts”: {
007 “start”: “node app.js”
008 },
009 “dependencies”: {
010 “express”: “3.x”
011 }
012 }

Run installation

Open your Terminal application or Windows command prompt and navigate into the project directory, inside of which you have saved your package.json file. As we have this file created with dependency information we can use the Node Package Manager to fetch and install Express for us. Run the following simple command to do this.

001> npm install 

Create main file

The basic requirements for an Express application include one JavaScript file to hold the library instantiation and route information. Create a new file called ‘app.’ in the project root. Inside of this we need to require the Express framework and create a new instance of the Express object for use within the actual application.

001	var express = require(‘express’);
002	var app = express(); 

First route

Express manages the application through a series of routes, defined explicitly by the developer, to ensure correct URL paths match and return expected responses. The routes are set using HTTP verbs. Each route defines the URL path and the request and response objects available to read and use. Finally we tell Node which port number to listen on.

001	app.get(‘/’, function(req, res) {
002	    res.send(‘Hello World.’);
003	});
004	app.get(‘/about’, function(req, res) {
005	    res.sendfile(‘./views/about.html’);
006	});
007	app.listen(3000);

Run in browser

To start the server, open Terminal or your command prompt and enter a command to fire it up. You can use either node app.js or, as we have defined a script declaration in the package.json file, npm start. The latter will run the same command for us. Once started, navigate to http://127.0.0.1:3000 and test the two routes defined in the previous step.

001	> node app.js
002	> npm start

Revise dependencies

Let’s amend the dependencies in the package.json file to install some new modules. We will be creating a URL shortener and using Handlebars as the templating engine. To ensure these are brought in to the application we’ll add them to the file as shown. To install them, simply run ‘npm install’ from the command line after you have saved the changes.

001	“dependencies”: {
002	    “express”: “3.x”,
003	    “short”: “2.x”,
004	    “hbs”: “*”
005	  } 

Clear out app.js

Open app.js and remove everything we’ve added so far. As we now have some updated modules we can restructure the core foundation and includes. We need to include Express and instantiate a new implementation, but we can now include the template system and set the port number to match the environment or a default value.

001	var express = require(‘express’),
002	    short = require(‘short’),
003	    app = express(),
004	    port = process.env.PORT || 3000,
005	    hbs = require(‘hbs’); 

Set the engine

We have loaded in the Handlebars module, but Express needs to know that we want to use it. By default it will work with all files with the ‘.hbs’ extension. Override this, setting the view engine to treat HTML files as dynamic files (or template-ready files). We then register the engine itself based on the file extension previously set.

001	app.set(‘view engine’, ‘html’);
002	app.engine(‘html’, hbs.__express); 



Connect to MongoDB

The short Node module included in the package.json file and installed earlier helps to manage all of the database interaction and dependencies for us. We still need to set the connection within the application, achieved by the following code. To install MongoDB locally, check out the official documentation here: docs.mongodb.org/manual/installation.

001	short.connect(“mongodb://localhost/short”);

Port revision

As part of the initial variable instantiation and requirements at the top of the application file, we have set the port number to be 3000 by default. This will be overridden if we deploy to any external hosting service such as Heroku and use the environment port number instead. The application will then be able to listen to the provided port.

001	app.listen(port, function () {
002	  console.log(‘Server running on port ‘ + port);
003	}); 

Shorten link route

Create a new route that will handle GET requests to shorten a URL. This will contain a global ‘match all’ parameter value to obtain the URL that will be shortened, which we can obtain from the request parameter’s value as the first index of the array. We can then make a call to the short module in order to generate a database promise.

001	app.get(‘/shorten/*’, function (req, res) {
002		var longURL = req.params[0],
003					shortURLPromise = short.generate
					({URL: longURL}); 
004		// more to be added here
005	});

Retrieve and output

Using the generated database promise we can adapt the route, adding in a new request to the short module for it to retrieve the shortened URL from the database by sending in the hash value as the key identifier. We can easily build up a string for the short URL to include the current host and send that string as content.

001	shortURLPromise.then(function(shortURLData) {
002		short.retrieve(shortURLData.hash).
		then(function(shortURLObject) {
003			var shortURL = [req.host, “:”, port, “/”
			, shortURLObject.hash].join(“”);
004			res.send(shortURL);
005		}, function(error) {
006		if (error) {
007			throw new Error(error);
008		}
009	});
010	}, function(error) {
011		if (error) {
012			throw new Error(error);
013		}
014	}); 

View generated output

Building an API, it would be nice to allow users to see a JSON output of the shortened URL values. Create a new route to expand and pass through the short hash value as the parameter. This will retrieve it from the database and output the returned object data as JSON directly to the user.

001	app.get(‘/expand/:hash’, checkHashExists, function 
	(req, res) {
002		var short_hash = req.params.hash;
003		short.retrieve(short_hash).then(function
		(shortURLObject) {
004			res.send(shortURLObject);
005		});
006	}); 

Manage redirections

Following a similar principle, create a new route that just picks up the short hash value as the prime URL structure. This too will retrieve the details from the database using the short.retrieve() method. In this route we can use Express to redirect the user directly over to the full URL, passing through an optional status code as well.

001	app.get(‘/:hash’, checkHashExists, function (
	req, res) {
002		var short_hash = req.params.hash;
003		short.retrieve(short_hash).		then(function(shortURLObject) {
004			res.redirect(302, shortURLObject.URL);
005		});
006	}); 

Using middleware

The last two routes were very similar and also included an optional callback function reference to checkHashExists(). Create this function below the routes. All requests to the two routes will first go through this method, which checks the hash exists and if it doesn’t, sends an error. If it does, it sends Express to the next method (the actual route).

001	function checkHashExists(req, res, next) {
002		var short_hash = req.params.hash;
003		short.retrieve(short_hash).then(function
		(shortURLObject) {
004			next();
005		}, function (error) {
006			if (error) {
007				res.send(‘URL not found!’, 404);
008			}
009		});
010	}

View all URLs

Since we have stored information in the database for all generated shortened URLs, we have access to a complete list of all saved values and can retrieve information using the short Node module. Create a new route for the root of the application, which will get a reference object containing all values using the list() method.

001	app.get(‘/’, function (req, res) {
002	  var listURLsPromise = short.list();
003	  // more code
004	}); 

Render template file

With the generated URLs returned as an object (an array of objects to be precise) we can use that data and then send it to an HTML template file, which can use Handlebars to render the content. The first value is the name of the template file, list.html, and the object contains dynamic data to use and display in the template itself.

001	listURLsPromise.then(function(urlData) {	
002		res.render(‘list’,{urls:urlData, count: urlData.
		length});
003	}, function(error) {
004		if (error) {
005			throw new Error(error);
006		}
007	});

Create template file

By default Express will look for all template files in a /views directory in the root of the application. Create this directory and generate a new file called ‘layout.html’ inside it. The Handlebars template syntax can loop over the data collection and output each value. For more information on the syntax, check out handlebarsjs.com.

Create layout files

At the moment, any requests to the root route will render just the HTML included within the view template file, no other surrounding HTML content. We can create a generic layout file in the views directory called ‘layout.html’, which will be applied to all template renders. The Handlebars syntax will display the route view yield.

Public assets

The application’s request procedure will inspect all available routes and return content accordingly based upon the URL pattern. This is not ideal for public assets such as favicons, images, JavaScript and CSS files. Create a new directory called ‘public’ in the root of the application structure and place any assets inside this folder.

001	mkdir ./public 

Declare static directory

To ensure Express checks for all static content within the public directory instead of comparing the URL patterns against the routes, we can set the static path in app.js. From now on, Express will first check this directory for a custom.css (for example) and, if it exists, it will return that static file without hitting the route process.

001	app.use(express.static(‘public’));



×