http://expressjs.com/guide/migrating-4.htmljavascript
Express 4 is a breaking change from Express 3. That means an existing Express 3 app will not work if you update the Express version in its dependencies.html
This article covers:java
The main changes in Express 4 are:node
See also:git
Express 4 no longer depends on Connect, and removes all the built-in middleware from its core, except express.static
. This means Express is now an independent routing and middleware web framework, and Express versioning and releases are not affected by middleware updates.github
With the built-in middleware gone, you must explicitly add all the middleware required to run your app. Simply follow these steps:web
npm install --save <module-name>
require('module-name');
app.use( ... );
The following table lists Express 3 middleware and their counterparts in Express 4.express
Express 3 | Express 4 |
---|---|
express.bodyParser | body-parser + multer |
express.compress | compression |
express.cookieSession | cookie-session |
express.cookieParser | cookie-parser |
express.logger | morgan |
express.session | express-session |
express.favicon | serve-favicon |
express.responseTime | response-time |
express.errorHandler | errorhandler |
express.methodOverride | method-override |
express.timeout | connect-timeout |
express.vhost | vhost |
express.csrf | csurf |
express.directory | serve-index |
express.static | serve-static |
Here is the complete list of Express 4 middleware.npm
In most cases, you can simply replace the old version 3 middleware with its Express 4 counterpart. For details, see the module documentation in GitHub.json
In version 4 you can now load middleware on a path with a variable parameter and read the parameter value from the route handler. For example:
app.use('/book/:id', function(req, res, next) { console.log('ID:', req.params.id); next(); })
Apps now implicitly load routing middleware, so you no longer have to worry about the order in which middleware is loaded with respect to the router
middleware.
The way you define routes is unchanged, but the routing system has two new features to help organize your routes:
app.route()
, to create chainable route handlers for a route path.express.Router
, to create modular mountable route handlers.The new app.route()
method enables you to create chainable route handlers for a route path. Since the path is specified in a single location, it helps to create modular routes and reduce redundancy and typos. For more information on routes, see Router() documentation.
Here is an example of chained route handlers defined using app.route()
.
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'); })
The other feature to help organize routes is a new class, express.Router
, that you can use to create modular mountable route handlers. A Router
instance is a complete middleware and routing system; for this reason it is often referred to as a "mini-app".
The following example creates a router as a module, loads a middleware in it, defines some routes, and mounts it on a path on the main app.
Create a router file named birds.js
in the app directory, with the following content:
var express = require('express'); var router = express.Router(); // middleware specific to this router router.use(function timeLog(req, res, next) { console.log('Time: ', Date.now()); next(); }) // define the home page route router.get('/', function(req, res) { res.send('Birds home page'); }) // define the about route router.get('/about', function(req, res) { res.send('About birds'); }) module.exports = router;
Then, load the router module in the app:
var birds = require('./birds'); ... app.use('/birds', birds);
The app will now be able to handle requests to /birds
and /birds/about
, along with calling the timeLog
middleware specific to the route.
The following table lists other small but important changes in Express 4.
Object | Description |
---|---|
Node | Express 4 requires Node 0.10.x or later and has dropped support for Node 0.8.x. |
http.createServer() |
The http module is no longer needed. The app is started using app.listen() . |
app.configure() |
app.configure() has been removed. Use process.env.NODE_ENV or app.get('env') to detect the environment and configure the app accordingly. |
json spaces |
The json spaces application property is disabled by default in Express 4. |
req.accepted() |
Use req.accepts() , req.acceptsEncodings() , req.acceptsCharsets() , and req.acceptsLanguages() . |
res.location() |
No longer resolves relative URLs. |
req.params |
Was an array, is now an object. |
res.locals |
Was a function, is now an object. |
res.headerSent |
Changed to res.headersSent . |
app.route |
Now available as app.mountpath . |
res.on('header') |
Removed. |
res.charset |
Removed. |
res.setHeader('Set-Cookie', val) |
Functionality is now limited to setting the basic cookie value. Use res.cookie() for added functionality. |
Here is an example of migrating an Express 3 application to Express 4. The files of interest are app.js
and package.json
.
Consider an Express v.3 application with the following app.js
file:
var express = require('express'); var routes = require('./routes'); var user = require('./routes/user'); var http = require('http'); var path = require('path'); var app = express(); // all environments app.set('port', process.env.PORT || 3000); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.methodOverride()); app.use(express.session({ secret: 'your secret here' })); app.use(express.bodyParser()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); // development only if ('development' == app.get('env')) { app.use(express.errorHandler()); } app.get('/', routes.index); app.get('/users', user.list); http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
The accompanying version 3 package.json
file might look something like this:
{ "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node app.js" }, "dependencies": { "express": "3.12.0", "jade": "*" } }
Begin the migration process by installing the required middleware for the Express 4 app and updating Express and Jade to their respective latest version with the following command:
$ npm install serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest jade@latest --save
Make the following changes to app.js:
The http
module is longer required, so remove var http = require('http');
The built-in Express middleware express.favicon
, express.logger
, express.methodOverride
, express.session
, express.bodyParser
and express.errorHandler
are no longer available on the express
object. You must install their alternatives manually and load them in the app.
You no longer need to load app.router
. It is not a valid Express 4 app object, so remove app.use(app.router);
Make sure the middleware are loaded in the right order - load errorHandler
after loading the app routes.
Start the app with app.listen()
instead of http.createServer
.
Running the above npm
command will update package.json
as follows:
{ "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node app.js" }, "dependencies": { "body-parser": "^1.5.2", "errorhandler": "^1.1.1", "express": "^4.8.0", "express-session": "^1.7.2", "jade": "^1.5.0", "method-override": "^2.1.2", "morgan": "^1.2.2", "multer": "^0.1.3", "serve-favicon": "^2.0.1" } }
Then, remove invalid code, load the required middleware, and make other changes as necessary. Then app.js
will look like this:
var express = require('express'); var routes = require('./routes'); var user = require('./routes/user'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var methodOverride = require('method-override'); var session = require('express-session'); var bodyParser = require('body-parser'); var multer = require('multer'); var errorHandler = require('errorhandler'); var app = express(); // all environments app.set('port', process.env.PORT || 3000); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); app.use(methodOverride()); app.use(session({ resave: true, saveUninitialized: true, secret: 'uwotm8' })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(multer()); app.use(express.static(path.join(__dirname, 'public'))); app.get('/', routes.index); app.get('/users', user.list); // error handling middleware should be loaded after the loading the routes if ('development' == app.get('env')) { app.use(errorHandler()); } app.listen(app.get(