Moving to Express 4迁移到Express 4

Overview

Express 4 is a breaking change from Express 3. Express 4是对Express 3的突破性更改。That means an existing Express 3 app will not work if you update the Express version in its dependencies.这意味着如果您在其依赖项中更新Express版本,现有的Express 3应用程序将无法工作。

This article covers:本文涵盖:

Changes in Express 4

There are several significant changes in Express 4:Express 4中有几个重大变化:

See also:

Changes to Express core and middleware systemExpress核心和中间件系统的更改

Express 4 no longer depends on Connect, and removes all built-in middleware from its core, except for the express.static function. express4不再依赖于Connect,并从其核心中删除了所有内置中间件(express.static函数除外)。This means that Express is now an independent routing and middleware web framework, and Express versioning and releases are not affected by middleware updates.这意味着Express现在是一个独立的路由和中间件web框架,并且Express版本控制和发布不受中间件更新的影响。

Without built-in middleware, you must explicitly add all the middleware that is 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模块: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 3Express 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.下面是Express 4中间件的完整列表

In most cases, you can simply replace the old version 3 middleware with its Express 4 counterpart. 在大多数情况下,您可以简单地将旧的版本3中间件替换为对应的Express 4中间件。For details, see the module documentation in GitHub.有关详细信息,请参阅GitHub中的模块文档。

app.use accepts parameters接受参数

In version 4 you can use a variable parameter to define the path where middleware functions are loaded, then read the value of the parameter from the route handler. For example:在版本4中,您可以使用变量参数定义加载中间件函数的路径,然后从路由处理程序读取参数值。例如:

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.应用程序现在隐式加载路由中间件,因此您不再需要担心中间件相对于router中间件的加载顺序。

The way you define routes is unchanged, but the routing system has two new features to help organize your routes:定义路线的方式不变,但路线系统有两个新功能可帮助组织路线:

app.route() method方法

The new app.route() method enables you to create chainable route handlers for a route path. 新的app.route()方法使您能够为路由路径创建可链接的路由处理程序。Because the path is specified in a single location, creating modular routes is helpful, as is reducing redundancy and typos. 因为路径是在单个位置指定的,所以创建模块化路由很有帮助,因为这可以减少冗余和打字错误。For more information about routes, see Router() documentation.有关路由的更多信息,请参阅Router()文档

Here is an example of chained route handlers that are defined by using the app.route() function.下面是使用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 that helps to organize routes is a new class, express.Router, that you can use to create modular mountable route handlers. 另一个有助于组织路由的功能是一个新类express.Router,您可以使用它创建模块化可装载的路由处理程序。A Router instance is a complete middleware and routing system; for this reason it is often referred to as a “mini-app”.Router实例是一个完整的中间件和路由系统;因此,它通常被称为“迷你应用程序”。

The following example creates a router as a module, loads middleware in it, defines some routes, and mounts it on a path on the main app.下面的示例将路由器创建为模块,在其中加载中间件,定义一些路由,并将其装载到主应用程序的路径上。

For example, create a router file named birds.js in the app directory, with the following content:例如,在应用程序目录中创建一个名为birds.js的路由器文件,包含以下内容:

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 the /birds and /birds/about paths, and will call the timeLog middleware that is specific to the route.该应用程序现在将能够处理对/birds/birds/about路径的请求,并将调用特定于路由的timeLog中间件。

Other changes其他变化

The following table lists other small but important changes in Express 4:下表列出了Express 4中的其他小而重要的更改:

Object对象 Description描述
Node.js Express 4 requires Node.js 0.10.x or later and has dropped support for Node.js 0.8.x.Express 4需要Node.js 0.10.x或更高版本,并且已放弃对Node.js 0.8.x的支持。

http.createServer()

The http module is no longer needed, unless you need to directly work with it (socket.io/SPDY/HTTPS). 不再需要http模块,除非您需要直接使用它(socket.io/SPDY/HTTPS)。The app can be started by using the app.listen() function.可以使用app.listen()函数启动应用程序。

app.configure()

The app.configure() function has been removed. app.configure()函数已被删除。Use the process.env.NODE_ENV or app.get('env') function to detect the environment and configure the app accordingly.使用process.env.NODE_ENVapp.get('env')函数检测环境并相应地配置应用程序。

json spaces

The json spaces application property is disabled by default in Express 4.在Express 4中,默认情况下禁用json spaces应用程序属性。

req.accepted()

Use req.accepts(), req.acceptsEncodings(), req.acceptsCharsets(), and req.acceptsLanguages().使用req.accepts()req.acceptsEncodings()req.acceptsCharsets()req.acceptsLanguages()

res.location()

No longer resolves relative URLs.不再解析相对URL。

req.params

Was an array; now an object.是一个数组;现在是一个对象。

res.locals

Was a function; now an object.是一种功能;现在是一个对象。

res.headerSent

Changed to res.headersSent.改为res.headersSent

app.route

Now available as app.mountpath.现在以app.mountpath的形式提供。

res.on('header')

Removed.已删除。

res.charset

Removed.已删除。

res.setHeader('Set-Cookie', val)

Functionality is now limited to setting the basic cookie value. 功能现在仅限于设置基本cookie值。Use res.cookie() for added functionality.使用res.cookie()添加功能。

Example app migration应用程序迁移示例

Here is an example of migrating an Express 3 application to Express 4. 下面是一个将Express 3应用程序迁移到Express 4的示例。The files of interest are app.js and package.json.感兴趣的文件是app.jspackage.json

Version 3 app

app.js

Consider an Express v.3 application with the following app.js file:考虑一个带有下列app.js文件的Express V.3应用程序:

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', 'pug')
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 (app.get('env') === 'development') {
  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:附带的版本3 package.json文件可能如下所示:

{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.12.0",
    "pug": "*"
  }
}

Process过程

Begin the migration process by installing the required middleware for the Express 4 app and updating Express and Pug to their respective latest version with the following command:通过安装Express 4应用程序所需的中间件并使用以下命令将Express和Pug更新到各自的最新版本,开始迁移过程:

$ npm install serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest pug@latest --save

Make the following changes to app.js:app.js进行以下更改:

  1. The built-in Express middleware functions 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.
  2. You no longer need to load the app.router function. It is not a valid Express 4 app object, so remove the app.use(app.router); code.
  3. Make sure that the middleware functions are loaded in the correct order - load errorHandler after loading the app routes.

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",
    "pug": "^2.0.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. 然后,删除无效代码,加载所需的中间件,并根据需要进行其他更改。The app.js file will look like this:app.js文件如下所示:

var http = require('http')
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()

// 所有环境
app.set('port', process.env.PORT || 3000)
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')
app.use(favicon(path.join(__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)

// 错误处理中间件应在加载路由后加载
if (app.get('env') === 'development') {
  app.use(errorHandler())
}

var server = http.createServer(app)
server.listen(app.get('port'), function () {
  console.log('Express server listening on port ' + app.get('port'))
})

Unless you need to work directly with the http module (socket.io/SPDY/HTTPS), loading it is not required, and the app can be simply started this way:除非您需要直接使用http模块(socket.io/SPDY/HTTPS),否则不需要加载它,应用程序可以通过以下方式简单启动:

app.listen(app.get('port'), function () {
  console.log('Express server listening on port ' + app.get('port'))
})

Run the app

The migration process is complete, and the app is now an Express 4 app. 迁移过程已完成,该应用程序现在是Express 4应用程序。To confirm, start the app by using the following command:要确认,请使用以下命令启动应用程序:

$ node .

Load http://localhost:3000 and see the home page being rendered by Express 4.

Upgrading to the Express 4 app generator升级到Express 4应用程序生成器

The command-line tool to generate an Express app is still express, but to upgrade to the new version, you must uninstall the Express 3 app generator and then install the new express-generator.

Installing安装

If you already have the Express 3 app generator installed on your system, you must uninstall it:如果系统上已安装Express 3 app generator,则必须卸载它:

$ npm uninstall -g express

Depending on how your file and directory privileges are configured, you might need to run this command with sudo.根据文件和目录权限的配置方式,您可能需要使用sudo运行此命令。

Now install the new generator:现在安装新的发电机:

$ npm install -g express-generator

Depending on how your file and directory privileges are configured, you might need to run this command with sudo.根据文件和目录权限的配置方式,您可能需要使用sudo运行此命令。

Now the express command on your system is updated to the Express 4 generator.现在,系统上的express命令更新为express 4生成器。

Changes to the app generator对应用程序生成器的更改

Command options and use largely remain the same, with the following exceptions:命令选项和使用基本保持不变,但以下情况除外:

Example

Execute the following command to create an Express 4 app:执行以下命令以创建Express 4应用程序:

$ express app4

If you look at the contents of the app4/app.js file, you will notice that all the middleware functions (except express.static) that are required for the app are loaded as independent modules, and the router middleware is no longer explicitly loaded in the app.如果查看app4/app.js文件的内容,您会注意到应用程序所需的所有中间件功能(express.static除外)都作为独立模块加载,路由器中间件不再显式加载到应用程序中。

You will also notice that the app.js file is now a Node.js module, in contrast to the standalone app that was generated by the old generator.您还将注意到,app.js文件现在是一个Node.js模块,与旧生成器生成的独立应用程序不同。

After installing the dependencies, start the app by using the following command:安装依赖项后,使用以下命令启动应用程序:

$ npm start

If you look at the npm start script in the package.json file, you will notice that the actual command that starts the app is node ./bin/www, which used to be node app.js in Express 3.

Because the app.js file that was generated by the Express 4 generator is now a Node.js module, it can no longer be started independently as an app (unless you modify the code). The module must be loaded in a Node.js file and started via the Node.js file. The Node.js file is ./bin/www in this case.

Neither the bin directory nor the extensionless www file is mandatory for creating an Express app or starting the app. They are just suggestions made by the generator, so feel free to modify them to suit your needs.

To get rid of the www directory and keep things the “Express 3 way”, delete the line that says module.exports = app; at the end of the app.js file, then paste the following code in its place:

app.set('port', process.env.PORT || 3000)

var server = app.listen(app.get('port'), function () {
  debug('Express server listening on port ' + server.address().port)
})

Ensure that you load the debug module at the top of the app.js file by using the following code:

var debug = require('debug')('app4')

Next, change "start": "node ./bin/www" in the package.json file to "start": "node app.js".

You have now moved the functionality of ./bin/www back to app.js. This change is not recommended, but the exercise helps you to understand how the ./bin/www file works, and why the app.js file no longer starts on its own.