Express.js 4 is the latest (as of May 2014) version of the most popular mature and robust Node.js framework for web apps, services and APIs. There are some breaking changes going from 3.x to 4.x, so here’s a brief migration guide:
- Replacing Unbundled Middleware in Express.js 4
- Removing Deprecated Methods from Express.js 4 Apps
- Other Express.js 4 Changes
- Express.js 4 Route Instance and Chaining It
- Further Express.js 4 Migration Reading Links
Replacing Unbundled Middleware in Express.js 4
Let’s start with the biggest change that will break most of your Express.js 3.x projects. This is also the most discussed news (and long awaited?) on the Internet. Yes, it’s unbundled middleware.
Personally, I’m not sure whether it’s good or bad, because I kind of liked not having to declare extra dependencies. However, I can see the arguments for unbundling as well, including things like keeping the Express.js module small, upgrading middleware packages independently, etc.
So what is unbundled middleware? Remember the magic middleware that we used by just typing app.use(express.middlwarename())
? Well, they were coming from the Connect library and now they are gone from Express.js. It was customary to write, for example app.use(express.cookieParser())
in Express.js 3.x. Those modules are very important and essential for pretty much any web application. They were part of the Connect library, but Express.js 4.x doesn’t have Connect as a dependency. This means that if we want to use it (and we sure do!), we’ll need to explicitly include middleware like this:
$ npm install body-parse@1.0.2 --save
And then in the Express.js main configuration file (e.g., app.js
), use the included module like this:
var bodyParser = require('body-parse')
... //other dependencies
app.use(bodyParser())
... //some other Express.js app configuration
Kapish?
Here’s the list of the unbundled middleware that developers will have to replace: all except static. That’s right, static was left out. In the list below, on the left the Express.js 3.x middleware names, and on the right side are their NPM module counterparts for the Express.js 4.x usage:
express.bodyParser
:body-parser
(GitHub)express.compress
:compression
(GitHub)express.timeout
:connect-timeout
(GitHub)express.cookieParser
:cookie-parser
(GitHub)express.cookieSession
:cookie-session
(GitHub)express.csrf
:csurf
(GitHub)express.error-handler
:errorhandler
(GitHub)express.session
:express-session
(GitHub)express.method-override
:method-override
(GitHub)express.logger
:morgan
(GitHub)express.response-time
:response-time
(GitHub)express.favicon
:serve-favicon
(GitHub)express.directory
:serve-index
(GitHub)express.static
:serve-static
(GitHub)express.vhost
:vhost
(GitHub)
To make matters a bit more complicated, Express.js/Connect team is dropping support for the following modules and recommending that you use alternatives:
cookieParser
: cookies and keygriplimit
: raw-bodymultipart
: connect-multiparty, connect-busboyquery
: qsstaticCache
: st, connect-static
Many of these unbundled Express.js/Connect modules are looking for maintainers; make a dent in the Node.js universe!
Removing Deprecated Methods from Express.js 4 Apps
app.configure()
I don’t think most people ever used it. app.configure()
was a sugar-coating which was nice but a non-essential piece mostly meant for setting up environments. If you have it, just replace app.configure('name', function(){...})
with if (process.env.NODE_ENV === 'name') {...}
. For example, this old Express.js 3 production configuration:
app.configure('production', function() {
app.set('port', 80)
})
In Express.js 4.x, becomes:
if (process.env.NODE_ENV === 'production) {
app.set('port', 80)
})
PS: If you look into Express.js 3.x code on GitHub, that’s exactly what app.configure()
did. ;-)
app.router
One of the good changes is that the need to write app.router
has been eliminated! So now, basically the order of middleware and routes is the only thing that counts, but before developers were able to augment the order of execution by placing app.router
somewhere in the middle.
If you had any middleware that is supposed to be after the routes (but in the old wasn’t due to deprecated app.router
) move it after the route, just in the order you want them.
For example before, there is error handling middleware which is executed after routes in the Express.js 3.x:
app.use(express.cookieParser())
app.use(app.router)
app.use(express.errorHandler())
app.get('/', routes.index)
app.post('/signup', routes.signup)
Migrates into this code in Express.js 4.x:
var cookieParse = require('cookie-parser')
var errorHandler = require('errorhandler')
...
app.use(cookieParser())
app.get('/', routes.index)
app.post('/signup', routes.signup)
app.use(errorHandler())
In other words, app.use()
and routes with verbs such as app.get()
, app.post()
, app.put()
and app.del()
became equal counterparts.
res.on(‘header’)
res.on('header')
was removed from Connect 3.
res.charset
In Express.js 4.x, use res.type()
or res.set('content-type')
instead of res.charset
in Express.js 3.x.
res.headerSent
Use res.headersSent
instead.
req.accepted()
Use req.accepts()
instead.
req.accepted
in Express.js 4.x is powered by the module accepts
(GitHub), which was “extracted from Koa.js for general use” as the documentation says.
Other Express.js 4 Changes
app.use()
Amazingly, app.use()
now accepts URL parameters. This is another step towards making app.use()
and verb route methods equal and less confusing. The parameter is in the req.params
object.
For example, if we need to get ID from the URL, in Express.js 4.x middleware, we can write:
app.use('/posts/:slug', function(req, res, next) {
req.db.findPostBySlug(req.params.slug, function(post){
...
})
})
res.location()
It’s not resolving relative URL.
app.route
Look below at the section called “Express.js 4 Route Instance and Chaining It”.
json spaces
json spaces
is off by default in development
req.params
req.params
is an object, not an array.
res.locals
res.locals
is an object now.
req.is
req.is
in Express.js 4.x was replaced by the module type-is
(GitHub), which was also “extracted from [Koa.js](http://koajs.com for general use” as the documentation says.
Express.js Command-Line Generator
For the command-line generator use
$ sudo npm install -g express-generator
Instead of old plain $ sudo npm install -g express
.
Express.js 4 Route Instance and Chaining It
The app.route()
method gives us the new Express.js 4 Route instance, but before we explore it, let’s take a look at the router itself.
The Router class has been supercharged in Express.js 4.x. Before the app instance used router, but now we can create many route instances and use the for specific paths by attaching particular middleware and other logic. This can be used to re-organize code. This of Router as a mini Express.js application!
Here’s a basic example on how developers can use Router in Express.js 4.x. Let’s say we have reviews for two categories: books and games. The reviews logic is similar to and packaged as a router:
var express = require('express')
var app = express()
var router = express.Router()
router.use(function(req, res, next) {
//process each request
});
router.get('/', function(req, res, next) {
// get the home page for that entity
next();
});
router.get('/reviews', function(req, res, next) {
// get the reviews for that entity
next();
});
app.use('/books', router);
app.use('/games', router);
app.listen(3000);
app.route()
or router.route()
returns us the new Express.js 4.x route instance which we can chain like this:
router.route('/post/:slug')
.all(function(req, res, next) {
// runs each time
// we can fetch the post by id from the database
})
.get(function(req, res, next) {
//render post
})
.put(function(req, res, next) {
//update post
})
.post(function(req, res, next) {
//create new comment
})
.del(function(req, res, next) {
//remove post
})
While in Express.js we would have to type the same path again and again (asking for a typo mistake):
router.all('/post/:slug', function(req, res, next) {
// runs each time
// we can fetch the post by ID from the database
})
router.get('/post/:slug', function(req, res, next) {
//render post
})
router.put('/post/:slug', function(req, res, next) {
//update post
})
router.post('/post/:slug', function(req, res, next) {
//create new comment
})
router.delete('/post/:slug', function(req, res, next) {
//remove post
})
The same Route instance can also have its own middleware, param, and HTTP verb methods (as illustrated above).
Further Express.js 4 Migration Reading Links
So overall, the Express.js 4.x changes are not very dramatic, and the migration can go relatively painless. But just before you hit $ git checkout -b express4
to create a new branch for your migration from 3.x, think if you really need to do it! I know many successful production applications that haven’t updated their main framework versions. At Storify, we used to run Express.js 2.x when 3.x was available and it was a big deal. Another example from the Ruby world, I know many apps and developers who still work with Ruby on Rails 2.x when there is Ruby on Rails 4.x.
In case you decide to go with Express.js 4, don’t rely just on this brief overview. Take a look at these additional resources to help make a transition from Express.js 3.x to 4.x easier:
Wow! Who knew there was an English word? Now you’ve taught me two things! Ha!
“Kapish” is the correct English word: http://www.thefreedictionary.com/Kapish.
Great article! One thing though. :)
should be Capisce.
Source: Grew up Italian.
how to separate new router express 4 like this one app.get(‘/’, routes.index) ? thanks