Intro to the ExpressJS Web Application Framework
Per dictionary.com a framework is defined as :
an essential supporting structure of a building, vehicle, or object.
a basic structure underlying a system, concept, or text.
Therefore we can define a web application framework as :
A basic structure (or underlying pre-existing code) that supports the commonalities of the necessary components that make up a web application
This includes things like:
Express is a minimalist, un-opinionated web application framework written in NodeJS for building web applications.
It gives us the ability to get a web application up and running quickly and supports basic concepts related to the web without enforcing too much structure or adding too many features that may not be used in every application.
It is very good at allowing us to handle the different types of HTTP requests and setting up the routes for our application with the ability to be easily extended via NPM packages for other features like cookies, sessions, form inputs, etc...
//Create the project directory
$ mkdir myapp
$ cd myapp
//Initialize the application
$ npm init
entry point: (index.js) -> Change to app.js
//Install Express - it is a NPM module like anything else
$ npm install express --save
//Create our app.js entry point as defined in package.json
$ touch app.js
First we create a new NPM project and install the Express NPM module
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
Next we add a few basic constructs to create our web application
And to run your application:
#Using node
$ node app.js
#Using nodemon
$ nodemon app.js
Try it out: http://localhost:3000
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.get('/about', function(req, res) {
res.send('We are awesome!');
}
app.get('/faq', function(req, res) {
res.send('What you need?');
}
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
We can easily add more routes by adding more "route handlers" where the method is the HTTP method of the request:
// respond with contact form on the contact page
app.get('/contact', function (req, res) {
res.send('...<form>....'); //Example shorthand text for HTML form
});
// accept POST request on the contact page
app.post('/contact', function (req, res) {
res.send('Got a POST request');
});
// accept PUT request at /user
app.put('/user', function (req, res) {
res.send('Got a PUT request at /user');
});
// accept DELETE request at /user
app.delete('/user', function (req, res) {
res.send('Got a DELETE request at /user');
});
Like we said the method reflects the HTTP verb of the type of request our application has received so we can easily handle any type of request:
// respond with contact form on the contact page
app.use(express.static('public'));
Our application will also serve images, JavaScript and CSS files. We don't need Node to "process" these requests so we tell Express to "use" a static directory that we define as the location to look for these requests.
Express is smart enough to know what kind of requests are static files and to look here first for those requests.
This saves your server processing cycles for not having to handle these requests by cycling through lines of code or writing a route handler for every file imagineable.
var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.get('/contact', function (req, res) {
res.send('...<form>....'); //Example shorthand text for HTML form
});
app.post('/contact', function (req, res) {
res.send('Got a POST request');
});
app.put('/user', function (req, res) {
res.send('Got a PUT request at /user');
});
app.delete('/user', function (req, res) {
res.send('Got a DELETE request at /user');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
If we have multiple HTTP methods for a single route we can use app.route and chain our methods for handling a single URL path for multiple types of requests
app.route('/book')
.get(function(req, res) {
res.send('Get a random book');
})
.post(function(req, res) {
res.send('Add a book');
})
.put(function(req, res) {
res.send('Update the book');
});
We can also use RegEx for matching patterns of routes to all be handled by a single route handler
// will match acd and abcd
app.get('/ab?cd', function(req, res) {
res.send('ab?cd');
});
// will match abcd, abbcd, abbbcd, and so on
app.get('/ab+cd', function(req, res) {
res.send('ab+cd');
});
// will match abcd, abxcd, abRABDOMcd, ab123cd, and so on
app.get('/ab*cd', function(req, res) {
res.send('ab*cd');
});
// will match /abe and /abcde
app.get('/ab(cd)?e', function(req, res) {
res.send('ab(cd)?e');
});
We don't really want to pollute our main app.js file with a ton of routes so it's best practice to create modules that export our routes for larger applications
//File path: {{project_directory}}/routes/users.js
var express = require('express');
var router = express.Router();
//GET http://localhost:3000/users
router.get('/', function(req, res) {
res.send('All users');
});
//GET http://localhost:3000/users/1
router.get('/:id', function(req, res) {
res.send('Some dude');
});
//POST http://localhost:3000/users
router.post('/', function(req, res) {
res.send('Creating a dude');
}
//PUT http://localhost:3000/users/1
router.put('/:id', function(req, res) {
res.send('Updated a dude');
}
module.exports = router;
var users = require('./routes/users');
.
.
.
//Defer all routes matching
//http://localhost:3000/users to module
app.use('/users', users);
.
.
.
Every HTTP request is designed to return an HTTP response and Express gives us methods to send multiple types of responses:
res.download() | Prompt a file to be downloaded. |
res.end() | End the response process. |
res.json() | Send a JSON response. |
res.jsonp() | Send a JSON response with JSONP support. |
res.redirect() | Redirect a request. |
res.render() | Render a view template. |
res.send() | Send a response of various types. |
res.sendFile | Send a file as an octet stream. |
res.sendStatus() | Set the response status code and send its string representation as the response body. |
app.locals - Used for defining application level variables that are accessible anywhere in your application
Express has gone through major revisions between version 3.x and 4.x. When looking at documentation make sure it is referencing the proper version you are using.
Even though we don't handle HTTP headers manually as we did previously, they are still accessible on the req object. Take a look at the docs for the Request/Response objects to see what properties are available.