http://expressjs.com/guide/migrating-4.html

 

Overview

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.

This article covers:

Changes in Express 4

The main changes in Express 4 are:

See also:

Changes to Express core and middleware system

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.

With the built-in middleware gone, you must explicitly add all the middleware required to run your app. Simply follow these steps:

  1. Install the module: npm install --save <module-name>
  2. In your app, require the module: require('module-name');
  3. Use the module according to its documentation: app.use( ... );

The following table lists Express 3 middleware and their counterparts in Express 4.

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.

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.

app.use accepts parameters

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();
})

The routing system

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:

  • A new method, app.route(), to create chainable route handlers for a route path.
  • A new class, express.Router, to create modular mountable route handlers.

app.route() method

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');
  })

express.Router class

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.

Other changes

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.

Example app migration

Here is an example of migrating an Express 3 application to Express 4. The files of interest are app.js and package.json.

Version 3 app

app.js

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'));
});

package.json

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": "*"
  }
}

Process

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:

  1. The http module is longer required, so remove var http = require('http');

  2. The built-in Express middleware express.faviconexpress.loggerexpress.methodOverrideexpress.sessionexpress.bodyParser and express.errorHandler are no longer available on the express object. You must install their alternatives manually and load them in the app.

  3. You no longer need to load app.router. It is not a valid Express 4 app object, so remove app.use(app.router);

  4. Make sure the middleware are loaded in the right order - load errorHandler after loading the app routes.

  5. Start the app with app.listen() instead of http.createServer.

Version 4 app

package.json

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"
  }
}

app.js

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.

相关文章: