Moving to Express 4迁移到Express 4

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.Express 4是Express 3的突破性变化。这意味着,如果您在其依赖项中更新Express版本,现有的Express 3应用程序将无法工作。

This article covers:本文涵盖:

Changes in Express 4Express 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. Express 4不再依赖于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('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. For details, see the module documentation in GitHub.在大多数情况下,您可以简单地将旧版本3的中间件替换为Express 4的对应物。有关详细信息,请参阅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', (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((req, res) => {
    res.send('Get a random book')
  })
  .post((req, res) => {
    res.send('Add a book')
  })
  .put((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.以下示例将路由器创建为模块,加载中间件init,定义一些路由,并将其挂载到主应用程序上的路径上。

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

var express = require('express')
var router = express.Router()

// middleware specific to this router
router.use((req, res, next) => {
  console.log('Time: ', Date.now())
  next()
})
// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page')
})
// define the about route
router.get('/about', (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.10x或更高版本,并已停止支持Node.js 0.8x。

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. Use res.cookie() for added functionality.功能现在仅限于设置基本cookie值。使用res.cookie()添加功能。

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.下面是一个将Express 3应用程序迁移到Express 4的示例。感兴趣的文件是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'), () => {
  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. 内置的Express中间件函数express.faviconexpress.loggerexpress.methodOverrideexpress.sessionexpress.bodyParserexpress.errorHandler在Express对象上不再可用。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.您不再需要加载app.router函数。它不是有效的Express 4应用程序对象,因此请删除app.use(app.router);代码。

  3. Make sure that the middleware functions are loaded in the correct order - load errorHandler after loading the app routes.确保中间件函数以正确的顺序加载——加载应用程序路由后加载errorHandler

Version 4 app版本4应用程序

package.json

Running the above npm command will update package.json as follows:运行上述npm命令将更新package.json,如下所示:

{
  "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()

// all environments
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)

// error handling middleware should be loaded after the loading the routes
if (app.get('env') === 'development') {
  app.use(errorHandler())
}

var server = http.createServer(app)
server.listen(app.get('port'), () => {
  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'), () => {
  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. To confirm, start the app by using the following command:迁移过程已完成,该应用程序现在是Express 4应用程序。要确认,请使用以下命令启动应用程序:

$ 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.生成Express应用程序的命令行工具仍然是express,但要升级到新版本,您必须卸载Express 3应用程序生成器,然后安装新的express-generator

Installing 安装

If you already have the Express 3 app generator installed on your system, you must uninstall it:如果您的系统上已经安装了Express 3应用程序生成器,则必须卸载它:

$ 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除外)都是作为独立模块加载的,router中间件不再明确地加载在应用程序中。

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.如果你查看package.json文件中的npm start脚本,你会注意到启动应用程序的实际命令是node ./bin/www,它曾经是Express 3中的node app.js

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). 因为Express 4生成器生成的app.js文件现在是Node.js模块,所以它不能再作为应用程序独立启动(除非您修改代码)。The module must be loaded in a Node.js file and started via the Node.js file. 该模块必须加载到Node.js文件中,并通过Node.js文件启动。The Node.js file is ./bin/www in this case.在这种情况下Node.js文件是./bin/www

Neither the bin directory nor the extensionless www file is mandatory for creating an Express app or starting the app. 创建Express应用程序或启动应用程序时,bin目录和无扩展名的www文件都不是必需的。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:要摆脱www目录并保持“Express 3 way”,请删除module.exports = app;这一行;在app.js文件的末尾,然后将以下代码粘贴到其位置:

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

var server = app.listen(app.get('port'), () => {
  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:使用以下代码确保在app.js文件顶部加载debug模块:

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

Next, change "start": "node ./bin/www" in the package.json file to "start": "node app.js".下一步,将package.json文件中的"start": "node ./bin/www"改为"start": "node app.js"

You have now moved the functionality of ./bin/www back to app.js. 您现在已经移动了./bin/www的功能返回到app.jsThis 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.不建议进行此更改,但此练习可帮助您了解./bin/www文件如何起作用,以及为什么app.js文件不再独立启动。