Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: v5 release blog post #1616

Merged
merged 27 commits into from
Oct 15, 2024
Merged
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3c8ab5e
feat: v5 release
wesleytodd Sep 13, 2024
d2c022b
delete duplicated removal notices
jonchurch Oct 7, 2024
5481ac0
Update _posts/2024-09-12-v5-release.md
jonchurch Oct 7, 2024
26d16fc
Update _posts/2024-09-12-v5-release.md
jonchurch Oct 7, 2024
7bd3c54
typos, :name* change per blake
jonchurch Oct 7, 2024
397d300
General edits, some review feedback
crandmck Oct 9, 2024
0c430e7
Add a missing TO DO
crandmck Oct 9, 2024
9daa4c1
docs: removed ambiguous reference
UlisesGascon Oct 9, 2024
5759126
docs: Removed TODO
UlisesGascon Oct 9, 2024
1712f98
docs: linting
UlisesGascon Oct 9, 2024
3e74ca8
docs: added sponsorship link
UlisesGascon Oct 9, 2024
f63fb37
docs: added links to CVE-2024-45590, security triage team and last bl…
UlisesGascon Oct 9, 2024
0757b4b
docs: improved metadata
UlisesGascon Oct 9, 2024
eea1255
docs: added explanation in the deprecated APIs
UlisesGascon Oct 9, 2024
3e0f923
docs: added section for Migration and Security Guidance
UlisesGascon Oct 9, 2024
88dcaef
Final polish, add toc links to breaking change sections
crandmck Oct 11, 2024
d9fbc6e
Change xref to migration guide from changelog
crandmck Oct 12, 2024
5b1b2a0
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
1cd04c1
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
7c2104c
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
c31e217
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
eacff0c
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
7cd9b15
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
87408ca
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
ae42d70
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
cf462b6
Update _posts/2024-09-12-v5-release.md
UlisesGascon Oct 15, 2024
146185b
Move file to change post date
crandmck Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions _posts/2024-09-12-v5-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
title: Express v5
tags: site-admin
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
author: Wes Todd
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
---

Ten years ago the [Express v5 release PR](https://github.com/expressjs/express/pull/2237) was opened. It is now merged and published! There's a lot to be excited about, but we want to recognize the work of all our contributors, especially Doug Wilson who spent the last 10 years ensuring Express was the most stable project around. Without these contributions this release could not have happened.
excited to finally share with you some of the work we have been doing. As you might be aware, the [v5 release which has been in progress since July 14th
2014](https://github.com/expressjs/express/pull/2237) is now published and merged. There is a lot to talk about in the release, but I want to take a second to recognize the work of
many contributors over the years, especially @dougwilson who tirelessly maintained one of the most stable projects in the ecosystem over the past 10 years. Without the work from so
many, this release would not have happened so if you are among these contributors please give yourself a pat on the back.

So what happened 8 months ago? We went public with a proposed plan to move [Express Forward](https://github.com/expressjs/discussions/issues/160). This plan included re-committing
crandmck marked this conversation as resolved.
Show resolved Hide resolved
to the governance we had outlined many years before and added some things to help onboard more contributors to help kickstart progress again. It might not seem important to folks
who are less involved in Open Source, but project governance is critical to larger projects health. I want to thank the [OpenJS Foundation Cross Project
crandmck marked this conversation as resolved.
Show resolved Hide resolved
Council](https://github.com/openjs-foundation/cross-project-council/) and its members for helping us put together this plan.

## So what about v5?

Lets start by mentioning how **boring** this release is meant to be. I know this might seem like an odd thing to say, but it was truly our goal to keep this release as simple as we
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
could while unblocking ourselves to make larger and more impactful changes in future releases. This means we focused on things like dropping support for older Node.js versions,
addressing long standing security concerns, and updating the projects process to make things more maintainable for maintainers. To most folks these sound pretty **boring**, but to
us this means we can more easily ship future feature releases with the more exciting changes.

Before I move onto the changes for Express users we need to address the timeline and reason we released v5 when we did and on the `next` dist-tag. As part of reviving the project,
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
we started a [Security Working Group](https://github.com/expressjs/security-wg) and security triage team to help us ensure we address the growing needs around Open Source Supply
Chain Security. As part of this we undertook a security audit (more details to come on that) which uncovered a few things. Additionally while giving this aspect more attention, we
uncovered some other problems which needed to be addressed. This meant that in addition to the normal work we would do in public issues, we had many stacked features being worked
on in private forks. These required orchestration when releasing to enure the code and CVE reports went out together. So while we recognize that not having this blog post, our
changelog, and the documentation updated in advance was not ideal, with our limited contributor base we felt it was more important to focus on getting the secure and stable code
released.

We will be publishing more details on our LTS plans, including dates when we plan to move from `next` to `latest`, as soon as we can. But for now, if you are uncomfortable being on
the bleeding edge (even if it is a rather dull edge) then please consider waiting until we move to `latest` to upgrade. That said, we look forward to working with you all as you
upgrade to support and address any bugs you encounter.

## The Breaking Changes

As I said above, we did the minimum number of breaking changes we could. I try here to list them in order of impact to application owners, but there are a fair number of subtle
changes burried in here which you should read the changelog for more details on.

### Goodbye Node.js 0.10, Hello Node 18 and Up

We dropped support for Node.js versions lower than 18. This was a long time coming, but it is probably the most important change for us as maintainers of these libraries. Keeping old
Node.js version support was holding us back from many critical performance and maintainability changes. Now that we have dropped these versions we have more stable and maintainable
CI, we can start adopting some newer language and runtime features, and we can drop many dependencies which are no longer required.

We recognize that this might mean some enterprises have difficulty with older or "parked" applications, and because of this we are working on a partnership with HeroDevs to offer
crandmck marked this conversation as resolved.
Show resolved Hide resolved
"Never Ending Support" which will include critical security patches even after v4 enters End-of-Life (more on these plans will come soon). That said, we strongly suggest that folks
update to modern Node.js versions as soon as possible.

### Path Matching and Regular Expressions

We updated from `[email protected]` to `[email protected]` in v5, needless to say there were many years of changes in this. If you were using any of the 5.0.0-beta releases, we
landed a last minute update which greatly changed the path semantics so we could [remove any ReDoS chances going forward](https://blakeembrey.com/posts/2024-09-web-redos/). For
more detailed changes, [see the `path-to-regexp` readme](https://github.com/pillarjs/path-to-regexp?tab=readme-ov-file#express--4x).

#### 1. No more regex. We dropped support for sub-expression regular expressions (ex. `/:foo(\\d+)`).

This is one of the most common patterns in wide use which we have removed. The unfortunate nature of regular expressions is how easy it is to write one with exponential time behaviors
when parsing input. The dreaded ReDoS. It turns out it is very difficult to prevent users from doing this, and as a library which converts strings to regular expressions, we are on
the hook for the security aspects of this.

*How to migrate:* We recommend using more robust input validation libraries. [There are many on `npm`](https://www.npmjs.com/search?q=validate%20express) depending on your needs.
Shameless plug from the author, I maintain [a middleware based "code first" OpenAPI library](https://www.npmjs.com/package/@wesleytodd/openapi) for this kind of thing.
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved

#### 2. Splats, optional, and captures oh my. Simplified patterns for common route patterns.

With the removal of regular expression semantics comes other small but impactful changes to how you write your routes.

1. `:name?` becomes `{:name}`. Usage of `{}` for optional parts of your route means you can now do things like `/base{/:optional}/:required` and what parts are actually optional is
much more explicit.
2. `*` becomes `*name`.
3. `:name+` is equivalent to a `*name` and so has been removed
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
4. New reserved characters: `(`, `)`, `[`, `]`, `?`, `+`, & `!`. These have been reserved to leave room for future improvements and to prevent mistakes when migrating where those
characters mean specific things in previous versions.

*How to migrate:* (@wesleytodd to provide more info with codemods and migration tools)

#### 3. Name everything. Ordered numerical parameters are not supported.

In Express v4, using regex capture groups you could get numerical parameters (ex. `/user(s?)` => `req.params[0] === 's'`). Now all params must be named. Along with requiring a
name, we now support all valid JavaScript identifiers or quoted (ex. `/:"this"`).

### Promise Support

This one may be a bit contentious, but I `Promise` we are moving in the right direction. We have added support for returned *rejected* promises from middleware raising errors. This
*does not include* calling `next` from returned *resolved* promises. There are a lot of edge cases in old express apps around expectations of `Promise` behavior, and before we can
run we need to walk. For most folks, this means you can now write middleware like the following:

```javascript
app.use(async (req, res, next) => {
req.locals.user = await getUser(req);
next();
});
```

Notice that we use `async/await` and the `getUser` call may throw (user does not exist, db is down, etc), but we still call `next` if it is successful. We dont need to catch the
error in line anymore if we want to rely on error handling middleware instead because the router will now catch the rejected promise and treat that as calling `next(err)`.

*editorial note:* Error handling is a huge topic, but one hill I will die on is that errors should be handled as close to the error site as possible. So while this is now handled
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
in the router, I would strongly urge you to catch this kind of error within the middleware and handle it without relying on separate error handling middleware.

### Body Parser

We made an assortment of `body-parser` changes:

- Add option to customize the urlencoded body depth with a default value of 32 (@TODO see CVE)
- Remove deprecated `bodyParser()` combination middleware
- `req.body` is no longer always initialized to `{}`
- `urlencoded` parser now defaults `extended` to false
- Added brotli support

### Deprecated API Method Signatures Removed in Express v5

We have removed a number of deprecated API method signatures, many of which were carried over from v3 and deprecated under v4. Below are the changes you need to make:

- `res.redirect('back')` and `res.location('back')`: The magic string `'back'` is no longer supported. Use `req.get('Referrer') || '/'` explicitly instead.
- `res.send(status, body)` and `res.send(body, status)` signatures: Use `res.status(status).send(body)`.
- `res.send(status)` signature: Use `res.sendStatus(status)` for simple status responses, or `res.status(status).send()` for sending a status code with an optional body.
- `res.redirect(url, status)` signature: Use `res.redirect(status, url)`.
- `res.json(status, obj)` and `res.json(obj, status)` signatures: Use `res.status(status).json(obj)`.
- `res.jsonp(status, obj)` and `res.jsonp(obj, status)` signatures: Use `res.status(status).jsonp(obj)`.
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved
- `app.param(fn)`: This method has been deprecated. Instead, access parameters directly via `req.params`, or use `req.body` or `req.query` as needed.
- `app.del('/', () => {})` method: Use `app.delete('/', () => {})` instead.
- `req.acceptsCharset`: Use `req.acceptsCharsets` (plural).
- `req.acceptsEncoding`: Use `req.acceptsEncodings` (plural).
- `req.acceptsLanguage`: Use `req.acceptsLanguages` (plural).
- `res.sendfile` method: Use `res.sendFile` instead.

## Our work is just starting
UlisesGascon marked this conversation as resolved.
Show resolved Hide resolved

I know it seems like an odd thing to announce a "boring" major version release and then say the work is only starting after 10 years, but we hope that the ecosystem sees how
important this release is as a milestone toward a server side JavaScript ecosystem which is a stable and reliable tool for companies, governments, educators, and hobby projects. It
is our commitment as the new stewards of the Express project to do our best to help the ecosystem move forward with these goals in mind. If you would like to support this work,
which we do on a volunteer basis, please consider supporting the project and it's maintainers via our sponsorship opportunities (@TODO link here).
Loading