Moving to Express 5迁移到Express 5
Overview概述
Express 5 is not very different from Express 4; although it maintains the same basic API, there are still changes that break compatibility with the previous version. Therefore, an application built with Express 4 might not work if you update it to use Express 5.Express 5与Express 4没有太大区别;尽管它维护了相同的基本API,但仍有一些更改破坏了与以前版本的兼容性。因此,如果将使用Express 4构建的应用程序更新为使用Express 5,则可能无法运行。
To install this version, you need to have a Node.js version 18 or higher. Then, execute the following command in your application directory:要安装此版本,您需要Node.js版本18或更高版本。然后,在应用程序目录中执行以下命令:
npm install "express@5"
You can then run your automated tests to see what fails, and fix problems according to the updates listed below. After addressing test failures, run your app to see what errors occur. You’ll find out right away if the app uses any methods or properties that are not supported.然后,您可以运行自动测试以查看失败的原因,并根据下面列出的更新修复问题。解决测试失败后,运行您的应用程序以查看发生了什么错误。您将立即发现该应用程序是否使用了任何不受支持的方法或属性。
Express 5 CodemodsExpress 5 Codemods
To help you migrate your express server, we have created a set of codemods that will help you automatically update your code to the latest version of Express.为了帮助您迁移express服务器,我们创建了一组codemods,可以帮助您自动将代码更新到最新版本的express。
Run the following command for run all the codemods available:运行以下命令以运行所有可用的codemods:
npx @expressjs/codemod upgrade
If you want to run a specific codemod, you can run the following command:如果要运行特定的codemod,可以运行以下命令:
npx @expressjs/codemod name-of-the-codemod
You can find the list of available codemods here.你可以在这里找到可用的codemods列表。
Changes in Express 5Express 5的变化
Removed methods and properties已删除方法和属性
app.del()
app.param(fn)
Pluralized method names复数方法名Leading colon in name argument to app.param(name, fn)app.param(name, fn)
的name
参数中的前导冒号req.param(name)
res.json(obj, status)
res.jsonp(obj, status)
res.redirect('back')
and和res.location('back')
res.redirect(url, status)
res.send(body, status)
res.send(status)
res.sendfile()
router.param(fn)
express.static.mime
express:router
debug logs调试日志
Changed改变
Path route matching syntax路径路由匹配语法Rejected promises handled from middleware and handlers从中间件和处理程序处理的被拒绝的promiseexpress.urlencoded
express.static dotfiles
app.listen
app.router
req.body
req.host
req.query
res.clearCookie
res.status
res.vary
Improvements改进
Removed methods and properties已删除方法和属性
If you use any of these methods or properties in your app, it will crash. So, you’ll need to change your app after you update to version 5.如果你在应用程序中使用这些方法或属性中的任何一个,它都会崩溃。因此,在更新到版本5后,您需要更改您的应用程序。
app.del()
Express 5 no longer supports the Express 5不再支持app.del()
function. If you use this function, an error is thrown. For registering HTTP DELETE routes, use the app.delete()
function instead.appdel()
函数。如果使用此函数,将抛出错误。要注册HTTP DELETE路由,请改用app.delete()
函数。
Initially, 最初,使用del
was used instead of delete
, because delete
is a reserved keyword in JavaScript. However, as of ECMAScript 6, delete
and other reserved keywords can legally be used as property names.del
而不是delete
,因为delete
是JavaScript中的保留键。但是,从ECMAScript 6开始,delete
和其他保留键可以合法地用作属性名。
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.del('/user/:id', (req, res) => {
res.send(`DELETE /user/${req.params.id}`)
})
// v5
app.delete('/user/:id', (req, res) => {
res.send(`DELETE /user/${req.params.id}`)
})
app.param(fn)
The app.param(fn)
signature was used for modifying the behavior of the app.param(name, fn)
function. It has been deprecated since v4.11.0, and Express 5 no longer supports it at all.app.param(fn)
签名用于修改app.param(name, fn)
函数的行为。自v4.11.0以来,它已被弃用,Express 5根本不再支持它。
Pluralized method names复数方法名
The following method names have been pluralized. In Express 4, using the old methods resulted in a deprecation warning. Express 5 no longer supports them at all:以下方法名称已被复数化。在Express 4中,使用旧方法会导致弃用警告。Express 5不再支持它们:
req.acceptsCharset()
is replaced by req.acceptsCharsets()
.req.acceptsCharset()
被替换为req.acceptsCharsets()
。
req.acceptsEncoding()
is replaced by req.acceptsEncodings()
.req.acceptsEncoding()
被替换为req.acceptsEncodings()
。
req.acceptsLanguage()
is replaced by req.acceptsLanguages()
.
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod pluralized-methods
// v4
app.all('/', (req, res) => {
req.acceptsCharset('utf-8')
req.acceptsEncoding('br')
req.acceptsLanguage('en')
// ...
})
// v5
app.all('/', (req, res) => {
req.acceptsCharsets('utf-8')
req.acceptsEncodings('br')
req.acceptsLanguages('en')
// ...
})
Leading colon (:) in the name for app.param(name, fn)
A leading colon character (:) in the name for the app.param(name, fn)
function is a remnant of Express 3, and for the sake of backwards compatibility, Express 4 supported it with a deprecation notice. Express 5 will silently ignore it and use the name parameter without prefixing it with a colon.
This should not affect your code if you follow the Express 4 documentation of app.param, as it makes no mention of the leading colon.
req.param(name)
This potentially confusing and dangerous method of retrieving form data has been removed. You will now need to specifically look for the submitted parameter name in the req.params
, req.body
, or req.query
object.
Note备注
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod req-param
// v4
app.post('/user', (req, res) => {
const id = req.param('id')
const body = req.param('body')
const query = req.param('query')
// ...
})
// v5
app.post('/user', (req, res) => {
const id = req.params.id
const body = req.body
const query = req.query
// ...
})
res.json(obj, status)
Express 5 no longer supports the signature Express 5不再支持签名res.json(obj, status)
. res.json(obj, status)
.。Instead, set the status and then chain it to the 相反,设置状态,然后将其链接到res.json()
method like this: res.status(status).json(obj)
.res.json()
方法,如下所示:res.status(status).json(obj)
。
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.post('/user', (req, res) => {
res.json({ name: 'Ruben' }, 201)
})
// v5
app.post('/user', (req, res) => {
res.status(201).json({ name: 'Ruben' })
})
res.jsonp(obj, status)
Express 5 no longer supports the signature res.jsonp(obj, status)
. Instead, set the status and then chain it to the res.jsonp()
method like this: res.status(status).jsonp(obj)
.
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.post('/user', (req, res) => {
res.jsonp({ name: 'Ruben' }, 201)
})
// v5
app.post('/user', (req, res) => {
res.status(201).jsonp({ name: 'Ruben' })
})
res.redirect(url, status)
Express 5 no longer supports the signature Express 5不再支持签名res.redirect(url, status)
. res.redirect(url, status)
。Instead, use the following signature: 相反,请使用以下签名:res.redirect(status, url)
.res.redirect(status, url)
。
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.get('/user', (req, res) => {
res.redirect('/users', 301)
})
// v5
app.get('/user', (req, res) => {
res.redirect(301, '/users')
})
res.redirect('back')
and 和res.location('back')
Express 5 no longer supports the magic string Express 5不再支持back
in the res.redirect()
and res.location()
methods. res.redirect()
和res.location()
方法中的魔术字符串back
。Instead, use the 相反,请使用req.get('Referrer') || '/'
value to redirect back to the previous page. req.get('Referrer') || '/'
值重定向回上一页。In Express 4, the 在Express 4中,res.redirect('back')
and res.location('back')
methods were deprecated.res.redirect('back')
和res.location('back')
方法已被弃用。
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod magic-redirect
// v4
app.get('/user', (req, res) => {
res.redirect('back')
})
// v5
app.get('/user', (req, res) => {
res.redirect(req.get('Referrer') || '/')
})
res.send(body, status)
Express 5 no longer supports the signature Express 5不再支持签名res.send(obj, status)
. res.send(obj, status)
。Instead, set the status and then chain it to the 相反,设置状态,然后将其链接到res.send()
method like this: res.status(status).send(obj)
.res.send()
方法,如下所示:res.status(status).send(obj)
。
Note
You can replace the deprecated signatures with the following command:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.get('/user', (req, res) => {
res.send({ name: 'Ruben' }, 200)
})
// v5
app.get('/user', (req, res) => {
res.status(200).send({ name: 'Ruben' })
})
res.send(status)
Express 5 no longer supports the signature res.send(status)
, where status
is a number. Instead, use the res.sendStatus(statusCode)
function, which sets the HTTP response header status code and sends the text version of the code: “Not Found”, “Internal Server Error”, and so on.
If you need to send a number by using the res.send()
function, quote the number to convert it to a string, so that Express does not interpret it as an attempt to use the unsupported old signature.
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.get('/user', (req, res) => {
res.send(200)
})
// v5
app.get('/user', (req, res) => {
res.sendStatus(200)
})
res.sendfile()
The res.sendfile()
function has been replaced by a camel-cased version res.sendFile()
in Express 5.
Note: In Express 5, res.sendFile()
uses the mime-types
package for MIME type detection, which returns different Content-Type values than Express 4 for several common file types:
- JavaScript files (.js): now “text/javascript” instead of “application/javascript”
- JSON files (.json): now “application/json” instead of “text/json”
- CSS files (.css): now “text/css” instead of “text/plain”
- XML files (.xml): now “application/xml” instead of “text/xml”
- Font files (.woff): now “font/woff” instead of “application/font-woff”
- SVG files (.svg): now “image/svg+xml” instead of “application/svg+xml”
Note
You can replace the deprecated signatures with the following command:您可以使用以下命令替换已弃用的签名:
npx @expressjs/codemod v4-deprecated-signatures
// v4
app.get('/user', (req, res) => {
res.sendfile('/path/to/file')
})
// v5
app.get('/user', (req, res) => {
res.sendFile('/path/to/file')
})
router.param(fn)
The router.param(fn)
signature was used for modifying the behavior of the router.param(name, fn)
function. It has been deprecated since v4.11.0, and Express 5 no longer supports it at all.
express.static.mime
In Express 5, mime
is no longer an exported property of the static
field.
Use the mime-types
package to work with MIME type values.
Important: This change affects not only direct usage of express.static.mime
but also other Express methods that rely on MIME type detection, such as res.sendFile()
. The following MIME types have changed from Express 4:
- JavaScript files (.js): now served as “text/javascript” instead of “application/javascript”
- JSON files (.json): now served as “application/json” instead of “text/json”
- CSS files (.css): now served as “text/css” instead of “text/plain”
- HTML files (.html): now served as “text/html; charset=utf-8” instead of just “text/html”
- XML files (.xml): now served as “application/xml” instead of “text/xml”
- Font files (.woff): now served as “font/woff” instead of “application/font-woff”
// v4
express.static.mime.lookup('json')
// v5
const mime = require('mime-types')
mime.lookup('json')
express:router debug logs
In Express 5, router handling logic is performed by a dependency. 在Express 5中,路由器处理逻辑由依赖关系执行。Therefore, the
debug logs for the router are no longer available under the express:
namespace.
In v4, the logs were available under the namespaces express:router
, express:router:layer
,
and express:router:route
. All of these were included under the namespace express:*
.
In v5.1+, the logs are available under the namespaces router
, router:layer
, and router:route
.
The logs from router:layer
and router:route
are included in the namespace router:*
.
To achieve the same detail of debug logging when using express:*
in v4, use a conjunction of
express:*
, router
, and router:*
.
# v4
DEBUG=express:* node index.js
# v5
DEBUG=express:*,router,router:* node index.js
Changed改变
Path route matching syntax路径路由匹配语法
Path route matching syntax is when a string is supplied as the first parameter to the app.all()
, app.use()
, app.METHOD()
, router.all()
, router.METHOD()
, and router.use()
APIs. The following changes have been made to how the path string is matched to an incoming request:
- The wildcard
*
must have a name, matching the behavior of parameters:
, use/*splat
instead of/*
// v4
app.get('/*', async (req, res) => {
res.send('ok')
})
// v5
app.get('/*splat', async (req, res) => {
res.send('ok')
})
Note
*splat
matches any path without the root path. If you need to match the root path as well /
, you can use /{*splat}
, wrapping the wildcard in braces.
// v5
app.get('/{*splat}', async (req, res) => {
res.send('ok')
})
The optional character可选字符?
is no longer supported, use braces instead.?
不再支持,请使用花括号。
// v4
app.get('/:file.:ext?', async (req, res) => {
res.send('ok')
})
// v5
app.get('/:file{.:ext}', async (req, res) => {
res.send('ok')
})
Regexp characters are not supported. For example:不支持Regexp字符。例如:app.get('/[discussion|page]/:slug', async (req, res) => { res.status(200).send('ok') })
should be changed to:
app.get(['/discussion/:slug', '/page/:slug'], async (req, res) => { res.status(200).send('ok') })
- Some characters have been reserved to avoid confusion during upgrade (
()[]?+!
), use\
to escape them. - Parameter names now support valid JavaScript identifiers, or quoted like
:"this"
.
Rejected promises handled from middleware and handlers
Request middleware and handlers that return rejected promises are now handled by forwarding the rejected value as an Error
to the error handling middleware. This means that using async
functions as middleware and handlers are easier than ever. When an error is thrown in an async
function or a rejected promise is await
ed inside an async function, those errors will be passed to the error handler as if calling next(err)
.
Details of how Express handles errors is covered in the error handling documentation.
express.urlencoded
The express.urlencoded
method makes the extended
option false
by default.
express.static dotfiles
In Express 5, the express.static
middleware’s dotfiles
option now defaults to "ignore"
. This is a change from Express 4, where dotfiles were served by default. As a result, files inside a directory that starts with a dot (.
), such as .well-known
, will no longer be accessible and will return a 404 Not Found error. This can break functionality that depends on serving dot-directories, such as Android App Links, and Apple Universal Links.
Example of breaking code:破解代码示例:
// v4
app.use(express.static('public'))
After migrating to Express 5, a request to /.well-known/assetlinks.json
will result in a 404 Not Found.
To fix this, serve specific dot-directories explicitly using the dotfiles: "allow"
option:
// v5
app.use('/.well-known', express.static('public/.well-known', { dotfiles: 'allow' }))
app.use(express.static('public'))
This approach allows you to safely serve only the intended dot-directories while keeping the default secure behavior for other dotfiles, which remain inaccessible.这种方法允许您仅安全地提供预期的点目录,同时保持其他点文件的默认安全行为,这些点文件仍然无法访问。
app.listen
In Express 5, the app.listen
method will invoke the user-provided callback function (if provided) when the server receives an error event. In Express 4, such errors would be thrown. This change shifts error-handling responsibility to the callback function in Express 5. If there is an error, it will be passed to the callback as an argument.
For example:
const server = app.listen(8080, '0.0.0.0', (error) => {
if (error) {
throw error // e.g. EADDRINUSE
}
console.log(`Listening on ${JSON.stringify(server.address())}`)
})
app.router
The app.router
object, which was removed in Express 4, has made a comeback in Express 5. In the new version, this object is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.
req.body
The req.body
property returns undefined
when the body has not been parsed. In Express 4, it returns {}
by default.
req.host
In Express 4, the req.host
function incorrectly stripped off the port number if it was present. In Express 5, the port number is maintained.
req.query
The req.query
property is no longer a writable property and is instead a getter. The default query parser has been changed from “extended” to “simple”.
res.clearCookie
The res.clearCookie
method ignores the maxAge
and expires
options provided by the user.
res.status
The res.status
method only accepts integers in the range of 100
to 999
, following the behavior defined by Node.js, and it returns an error when the status code is not an integer.
res.vary
The res.vary
throws an error when the field
argument is missing. In Express 4, if the argument was omitted, it gave a warning in the console
Improvements改进
res.render()
This method now enforces asynchronous behavior for all view engines, avoiding bugs caused by view engines that had a synchronous implementation and that violated the recommended interface.此方法现在对所有视图引擎强制执行异步行为,避免了由具有同步实现且违反推荐接口的视图引擎引起的错误。
Brotli encoding supportBrotli编码支持
Express 5 supports Brotli encoding for requests received from clients that support it.Express 5支持对从支持它的客户端收到的请求进行Brotli编码。