
Your first Express app
The best way to learn any new technology is to try it out using some practical examples. So, let's go ahead and build an Express app and find out how it works.
To ensure our experiments do not mess up our filesystem, let's create a directory named express-app
in your home directory and build our app there:
$ cd ~ $ mkdir express-app $ cd express-app
The app directory is ready and we can start building our first Express app.
The Express manifest file
In Chapter 1, What is Express?, we learned that Express apps are actually Node modules, which means our app also would need a manifest file. So, create a file named package.json
in the app directory.
The package.json
file can have more than a dozen fields, but for the sake for brevity, let's keep it minimal. Here is what it should look like:
{ "name": "test-app", "version": "0.0.1", "private": true, "scripts": { "start": "node app" }, "dependencies": { "express": "3.2.6", "jade": "*" } }
The fields used in the manifest file are explained in the following table:

Note
For an interactive guide to all the possible fields in a package.json
file, visit http://package.json.nodejitsu.com/.
We have the manifest file ready now. Executing the npm install
command in the directory will install all the dependencies in the directory:
$ npm install
You will see a huge wall of scrolling text, that's the dependencies being installed. Once it's done, you will find a new directory named node_modules
in the directory; that's where all the dependencies are installed. Because the directory is created and its contents generated by the npm install
command, you can safely delete this directory any time you need to for whatever reason, and regenerate it using the same command.
With the dependencies installed, we are now ready to start building out first Express app—from scratch.
Note
Each Express app hosts its own copy of Express framework in a directory named express
, under the node_modules
directory. You can safely play around with the framework files without affecting other apps. If you ever mess something up, just reinstall it by running npm install
in the app directory.
A very basic Express app
Let's create a very basic Express app to get us started. Create a file called app.js
and put the following code in it:
// Include the Node HTTP library var http = require('http'); // Include the Express module var express = require('express'); // Create an instance of Express var app = express(); // Start the app http.createServer(app).listen(3000, function() { console.log('Express app started'); }); // A route for the home page app.get('/', function(req, res) { res.send('Welcome!'); });
The app will listen on port 3000
and will have a very limited functionality. It will print "Welcome" when you load its home page, and return a 404 error for all other requests.
Note
HTTP 404 and 500 error handling is built into the router
middleware. The details about customizing these error handlers are covered in Chapter 4, Response from the Server.
You might have noticed that the route in the app is defined after the code for starting the server, but it works anyway. Isn't it shocking that it should even work?
The reason it works is because routes are defined on the app
object, which is passed to the HTTP API as a reference—any time you make a change on the app
object, it is reflected on the server.
Logically, it makes sense to defined the route first and then pass the app
object to the HTTP API, but I did afterwards to disruptively bring it to your attention about how the app
object is passed to the HTTP API—it is passed as a reference and its methods and properties can be accessed any time. Routes can be defined dynamically, but once defined cannot be redefined.
So much for its being the most important middleware; router
wasn't even mentioned in the app. So how does this app work at all?
The mere definition of a route implicitly adds the router
middleware at that point of the middleware stack. This feature might be acceptable in simple apps like ours, but in more complex apps, you will need to include the router
middleware explicitly, to ensure the proper order of middlewares in the stack. You will learn more about Express middleware in an upcoming section.
Starting and stopping the app
Since Express apps are Node programs, starting an Express app is similar to executing a Node program. In our case, the program resides in a file named app.js
, so this is how you will start the server:
$ node app > Express app started
To stop the server, press Ctrl + C.
Analyzing the output
Start the app and load http://localhost:3000
on your browser to see the output:

If you view the source of the web page and you will find that the server has sent the response in plain text.
How about sending some HTML in the response?
To send HTML response, just change res.send('Welcome!')
to res.send('<h1>Welcome!</h1>')
, and restart the server. Refresh the page to see the HTML formatted text, as shown in the following screenshot:

Note
For the changes made in application files to reflect, you need to restart the server. This can be a tedious process; you can make it easier for yourself by using supervisor, a Node module that will watch the application files and restart the server when any one of them changes. You can learn more about supervisor at https://github.com/isaacs/node-supervisor.
Now, how do we send a whole HTML page?
Express apps have a special component called views, wherein you write the necessary HTML using a templating language, which helps in separating HTML from the core app. Also, any changes made in the views will be reflected in the HTML output without requiring the server to be restarted.
Express app with views
Let's rewrite the app to use views. The view files can reside in any conveniently named directory on the filesystem, but it makes sense to have it right in the application directory.
So, let go ahead and create a directory for our views, named views
:
$ mkdir views
Now create two view files in the views
directory: one named index.jade
for the home page, another named hello.jade
for the hello web page.
The first thing you might notice about the view files is that they have the .jade
extension. This unfamiliar extension might make it look a little intimidating, but you will discover that it is very intuitive once you start using it.
Note
Note that Jade is just one of the many templating languages that is supported by Express. It is not mandatory to use Jade with Express. However, we focus on it especially because it was created keeping Express in mind, and is a natural fit for it. If you want to learn more about Jade, you can take a quick look at Chapter 5, The Jade Templating Language.
Express supports all templating languages that work with Node. It is just a matter of installing the right module and configuring your app to use it.
Let's familiarize ourselves with Jade by creating the content of the view files:
Here is the content for index.jade
:
html head title Welcome body Welcome!
And here is the content for hello.jade
:
html head title Hello body b Hello!
As you can notice, indentation is the key in Jade. You use consistent space- or tab-based indentations to nest HTML elements. We don't need to use the overly verbose HTML opening and closing tags. There is much more to Jade than this, but for now, you should be good to go with it. You will learn more about Jade in Chapter 5, The Jade Templating Language.
Tip
Make sure to consistently use spaces or tabs for indentation, or else Jade will throw an error.
Let's update app.js
to use our newly created views. The following code is commented well to help you understand what each relevant line of code is doing:
var http = require('http'); var express = require('express'); var app = express(); // Set the view engine app.set('view engine', 'jade'); // Where to find the view files app.set('views', './views'); // A route for the home page - will render a view app.get('/', function(req, res) { res.render('index'); }); // A route for /say-hello - will render a view app.get('/say-hello', function(req, res) { res.render('hello'); }); app.get('/test', function(req, res) { res.send('this is a test'); }); http.createServer(app).listen(3000, function() { console.log('App started'); });
In the updated app.js
, we have declared that we will be using the Jade templating engine, and have specified the views
directory for Jade. You can see we are using res.render()
for two of the routes to render views.
For a matched route, res.render()
will look for the view in the views
directory and render it accordingly
Restart the server and load http://localhost:3000
, http://localhost:3000/say-hello
, and http://localhost:3000/test
in the browser to see the new additions made to the app.
If you view the source of these web pages, you will find that the ones using views have generated complete HTML.
Make some changes in the view files and refresh the browser to see the changes. You don't need to restart the app to see the changes made in the view files, they are reflected instantly when you refresh the browser.
So far you have only seen a preview of Jade, you will learn much more in Chapter 5, The Jade Templating Language. Till then, let's continue understanding an Express app better.
A public directory for the app
We are now quite close to having a fully functional website, albeit a simple one. What remain now are CSS, JavaScript, images, and other files for the app. Where do we keep these files?
Express has a middleware called static
, using which we can mark a directory in the filesystem for serving static files for the app. Any file kept in these directories can be directly accessed via the browser.
This is how you use the static
middleware to set a directory for static resources:
app.use(express.static('./public'));
It is worth noting that you can set multiple static directories, if you need to:
app.use(express.static('./public')); app.use(express.static('./files')); app.use(express.static('./downloads'));
Let's create a static directory named public
and use it for our static content:
$ mkdir public $ mkdir public/images $ mkdir public/javascripts $ mkdir public/stylesheets
These directory names are chosen by convention, you can name them anything you want; as long as the static directory is set, they will work as expected. However, it is a good idea to stick to what I suggested, because those names are very commonly used by web developers around the world.
Create a nice looking image named logo.png
and keep it in the images
directory. I am using the following Packt logo:

Create a file named main.js
in the javascripts
directory with the following content:
window.onload = function() { document.getElementById('smile').innerHTML = ':)'; };
Create a file named style.css
in the stylesheets
directory with the following content:
#content { width: 220px; margin: 0 auto; text-align: center; border: 1px solid #ccc; box-shadow: 0 3px 4px #ccc; padding: 5px; }
Update index.jade
to include the newly added files:
html head title Welcome script(src='javascripts/main.js') link(rel='stylesheet', href='stylesheets/style.css') body #content img(src='images/logo.png') p WELCOME #smile
Update app.js
to set a static directory:
var http = require('http'); var express = require('express'); var app = express(); app.set('view engine', 'jade'); app.set('views', './views'); // Mark the public dir as a static dir app.use(express.static('./public')); app.get('/', function(req, res) { res.render('index'); }); http.createServer(app).listen(3000, function() { console.log('App started'); });
Restart the app and load the home page:

Congrats! Your first full-fledged Express app is up and running.