
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’));