Before we get started, just in case you missed them, here are quick links to the announcement post and Changelog:
Run the upgrade command and then we’ll go through all the breaking changes one by one:
yarn rw upgrade
But first a few admonitions:
Using
@redwoodjs/studio
?If you tried out Redwood Studio before this release, you’ll have to remove it from your root package.json before upgrading.
Studio is out of experimental in this release and uses a separate versioning scheme. You can add it right back after you upgrade via
yarn rw studio
.
Heads up
If you don’t have a clean working directory, commit or stash your changes before running codemods—they can overwrite files!
Arapaho Forest
This major version is part of the Arapaho Forest epochal version
Breaking Changes
- Node.js v20
prop-types
has been removed@testing-library/jest-dom
v6- dbAuth security improvements
- Server changes for dev and production parity
@redwoodjs/testing
no longer provides React types packages
Node.js v20
Quick summary
- Switch to Node.js >=20 using your favorite Node.js version manager (e.g.
nvm
)- Update your deploy provider’s Node.js version to >= 20 (quick links at the end)
- Update
engines.node
in your project’s root package.json; removeengines.yarn
while you’re there- If you have one, remove the
.nvmrc
file at the root of your project, especially if you’re deploying to Netlify- If you use GitHub Actions, don’t forget to update the version passed to
actions/setup-node
- If you use Docker, don’t forget to update your base image to Node.js 20
In this release, we’ve upgraded the framework to the latest Node.js LTS, version 20. That means a few things for you…
yarn rw build
now requires the correct version
Upgrading to Node.js v20 is inherently breaking in itself, but there’s another new behavior you’ll see at the CLI starting in this version. During build (yarn rw build
) we’re enforcing that your Node.js version is correct (>= 20.x). If you try to build with a version less than 20, you’ll get an error:
$ node -v
v18.19.0
$ yarn rw build
Error: Your Node.js version is v18.19.0, but Redwood requires >=v20.0.0.
Upgrade your Node.js version using `nvm` or a similar tool. See https://redwoodjs.com/docs/how-to/using-nvm.
The solution is to upgrade to Node.js v20. If you use nvm
, here’s how you’d do that:
# Install 20
$ nvm install 20
...
# Or, if you already have 20 installed:
$ nvm use 20
Now using node v20.11.0 (npm v10.2.4)
# Make sure to change the default alias to 20
# so that it persists in new shell sessions:
$ nvm alias default 20
default -> 20 (-> v20.11.0)
# Enable corepack again
$ corepack enable
Update engines.node in package.json
The package.json at the root of your project probably has an engines field that looks like this:
// package.json, before
...
"engines": {
"node": "=18.x",
"yarn": ">=1.22.21"
},
Some deploy providers use this to select the Node.js version. Since Redwood requires v20 now, update this to =20.x
:
// package.json, after
...
"engines": {
"node": "=20.x"
},
Just to clean things up while we’re here, you can also get rid of yarn in engines. Yarn v2+ ignores that field and new projects won’t be generated with it.
Remove the .nvmrc
file
Most projects up until now were generated with a .nvmrc
file. Most deploy providers don’t use this file at all. And for the ones that do (Netlify namely), it can be confusing because this file can request a different Node.js version than what’s specified in the dashboard or via another file (e.g. .node-version
), and then you’re debugging precedence conflicts. We recommend removing it and specifying the Node.js version for your deploy provider another way. Just know that Redwood doesn’t use it for anything locally.
GitHub Actions
If you use GitHub Actions, don’t forget to update actions/setup-node
:
# In a yaml file in .github/workflows...
- ...
- uses: actions/setup-node@v4
with:
node-version: 20
Deploy providers
Upgrading to Node.js v20 will mostly be a matter of upgrading the version used on your deploy provider. See the provided documentation for your deploy provider:
-
Baremetal
It’s all on you!
-
Coherence
Coherence uses Nixpacks. The
engines.node
field in your project’s root package.json should be enough but if it’s not you can set theNIXPACKS_NODE_VERSION
environment variable. -
Flightcontrol
Setting the Node.js Version for Nixpacks Builds - Flightcontrol
-
Netlify
-
Render
-
Vercel
Dockerfile
If you’re using Docker, be sure to update your base images to Node.js 20:
- FROM node:18-bookworm-slim as ...
+ FROM node:20-bookworm-slim as ...
prop-types
has been removed
Quick summary
- Remove
prop-types
from your web side’s package.json if it’s there- If you’re using
prop-types
, consider switching to TypeScript- If you want to keep using
prop-types
, you’ll have to import it yourself into the files where you’re using it (Redwood no longer auto imports it for you)
Up until this release, Redwood projects were still generated with the prop-types
dependency in their web side’s package.json:
// web/package.json
{
"name": "web",
...
"dependencies": {
"@redwoodjs/forms": "6.6.4",
"@redwoodjs/router": "6.6.4",
"@redwoodjs/web": "6.6.4",
"prop-types": "15.8.1", // 👈 This one
"react": "18.2.0",
"react-dom": "18.2.0"
},
...
}
prop-types
is an old package that provides runtime type checking for React props. It was popular before TypeScript.
We imagine that most users don’t use prop-types
, but if you do, the breaking change for you is that Redwood no longer automatically imports it into the files that use it. You’ll have to import it yourself. Or, just switch to TypeScript!
@testing-library/jest-dom
v6
v7 includes @testing-library/jest-dom
v6. This library is used in your web side tests. While this was mostly an internal upgrade, there are two changes you’ll have to make to your web side’s tsconfig.json
to get its types working properly:
- add
"../node_modules/@testing-library"
totypeRoots
- replace
"@testing-library/jest-dom"
with"jest-dom"
intypes
For example, here’s the difference in Create Redwood App’s web-side tsconfig.json
s between v6 and v7:
// web/tsconfig.json
{
"compilerOptions": {
...
"typeRoots": [
"../node_modules/@types",
"./node_modules/@types",
+ "../node_modules/@testing-library"
],
"types": [
"jest",
- "@testing-library/jest-dom"
+ "jest-dom"
],
...
dbAuth security improvements
Quick summary
- If you depend on more than just
id
andallowedUserFields
option- The reset token in
forgotPassword
is now passed as the second argument- If your user model had a primary key other than
id
(the value ofauthFields.id
), all users will be logged out on their next request after this version is deployed
For dbAuth users, we’ve made a breaking change to improve security. dbAuth has an internal function _sanitizeUser()
which removes sensitive fields from being returned to the client when calling functions like login
or forgotPassword
. It removes fields like hashedPassword
and salt
. But this is a deny list, not an allow list, so if you added your own potentially sensitive fields, they could be sent along in responses, depending on what data you chose to return from those functions.
This release reverses the strategy and instead makes you list the only fields that are allowed to be sent back. This is a breaking change for you in two ways:
- There’s a fallback that if the new
allowedUserFields
option is not defined we’ll assume["id", "email"]
by default, which is probably the smallest list that most people are using. So the majority of users can upgrade, make no code changes, and be fine. But, if you were counting on additional fields being returned by default, they now won’t be, thus the breaking-ness. forgotPassword
handler’s signature has changed, adding a second argument. Previously, a singleuser
object was passed which would contain theresetToken
to be emailed to the user. Since we’re now removing everything that isn’t in theallowedUserFields
list, this value would have been stripped out and not made available without some hacky workarounds. Instead, it’s now sent in a second argument to keep theuser
object “pure”. For more details, see the new documentation in the template here: redwood/packages/auth-providers/dbAuth/setup/src/templates/api/functions/auth.ts.template at 43bc6553aa3c55bb2de634a56e405970cdeb5b43 · redwoodjs/redwood · GitHub
The config set in api/src/functions/auth.js
will now look something like this (comments removed for clarity):
// api/src/functions/auth.{ts,js}
const forgotPasswordOptions = {
- handler: async (user) => {
+ handler: async (user, resetToken) => {
return user
},
expires: 60 * 60 * 24,
errors: {
usernameNotFound: 'Username not found',
usernameRequired: 'Username is required',
},
// more config...
const authHandler = new DbAuthHandler(event, context, {
db: db,
+ allowedUserFields: ["id", "email"],
authModelAccessor: 'user',
authFields: {
id: 'id',
username: 'email',
hashedPassword: 'hashedPassword',
salt: 'salt',
resetToken: 'resetToken',
resetTokenExpiresAt: 'resetTokenExpiresAt',
},
cookie: {
HttpOnly: true,
Path: '/',
SameSite: 'Strict',
Secure: process.env.NODE_ENV !== 'development',
},
forgotPassword: forgotPasswordOptions,
login: loginOptions,
resetPassword: resetPasswordOptions,
signup: signupOptions,
})
Server changes for dev and production parity
Quick summary
yarn rw serve
now behaves more like dev by serving the web and api side on separate portsyarn rw serve
now takes--webPort
,--webHost
,--apiPort
,--apiHost
, instead of just--port
- If you’re a heavy user of
api/server.config.js
, migrate to the newapi/src/server.ts
file usingyarn rw setup server-file
- The exports for
@redwoodjs/api-server
have changed; if you were depending on the internals of this package, upgrade to the new server file- You can now configure the web and api port and host via flags, env vars, and the toml
- You can no longer configure the web side via
api/server.config.js
Dev/prod parity
yarn rw dev
starts the dev server and yarn rw serve
(after you build) starts the production server. yarn rw dev
and yarn rw serve
were alike, but had a few differences.
One important difference was that yarn rw dev
starts two processes—one per side—and serves each side on separate ports. (By default, the web side is served at http://localhost:8910
and the api side is served at http://localhost:8911
.)
yarn rw serve
didn’t actually do the same thing. Instead, it started the web and the api side on the same host and port, http://0.0.0.0:8910
by default. It’d do this by registering your app’s api-side functions at /.redwood/functions
(the default [web].apiUrl
in redwood.toml
).
We fixed yarn rw serve
in this release so that it behaves more like dev. It’ll now start two servers the way dev does, with web on port 8910 and api on 8911, and proxy requests from the [web].apiUrl
to the api side.
server.config.js
is deprecated
If you were deploying “serverfully” and wanted to configure Redwood’s server, you could do so via the api/server.config.js
file. But this API only went so far. Many users expressed that they’d like more control. In this release, we’re deprecating the api/server.config.js
file in favor of a new API, createServer
:
yarn rw setup server-file
After running this setup command, you should have a new file at api/src/server.{ts,js}
:
// api/src/server.{ts,js}
import { createServer } from '@redwoodjs/api-server'
import { logger } from 'src/lib/logger'
async function main() {
const server = await createServer({
logger,
})
await server.start()
}
main()
This file is the entry point to your api server. And out of the box, it’s only the api server. (This file’s in the api side after all.)
If you want, you can run this file directly via Node.js (this is what our Dockerfile will do in the future), but it’s also hooked up to yarn rw dev
and yarn rw serve
:
$ yarn rw build
$ yarn node ./api/dist/server.js
Upgrading from the experimental server file
If you were using the experimental server file, thank you for trying it out and contributing to its development! Definitely let us know what you think of this new API.
The first iteration of the server file was very raw (for the original template, see redwood/packages/cli/src/commands/experimental/templates/server.ts.template at 31195fcadb9dccc6977ceee3413c1dd8d4c74f1c · redwoodjs/redwood · GitHub). It was more-or-less ejecting framework code, and the wiring the framework code was doing was cluttering the point of the file.
To upgrade to this new server file, we recommend renaming your existing server file to something like api/src/_server.ts
, running the setup command (yarn rw setup server-file
), and migrating over custom config.
In doing so, there are two things you’ll have to be aware of:
-
The config for the GraphQL function is pulled from
api/src/functions/graphql.ts
The first iteration of the server file got rid of the the GraphQL function in favor of configuring it inline via a plugin. In this new iteration, we reverted on that change. If you deleted the graphql function, you’ll want to restore it from the CRWA template and copy over any custom config you have.
-
Serving the web side in the server file isn’t recommended
The first version of the server file parsed an
--enableWeb
CLI flag to optionally serve the web side as well as the api side. We don’t recommend doing this anymore.yarn rw dev
won’t quite work with it because it doesn’t expect the sever file to also serve the web side.But… if you really want to, here’s how you could accomplish it: Serving both sides in the server file · GitHub
We understand this could be a bit of a lift. If you run into trouble, feel free to comment on this thread and we’re happy to help!
@redwoodjs/testing
no longer provides React types packages
Quick summary
- Make sure you have
@types/react
and@types/react-dom
in your web side’s package.json- The
@redwoodjs/testing
package used to bring in@types/react
and@types/react-dom
as dependencies. It no longer does to avoid issues with node_modules hoisting
Some time ago we made the change to list @types/react
and @types/react-dom
in Redwood project’s web-side package.json. The intention here was to be able to let you change the version of these packages since historically they’ve broken quite a bit and there was nothing we could do about it framework-side since they can be brought in by other packages.
We did this without removing the React types packages from @redwoodjs/testing
as dependencies which meant that eventually, it was very likely that two different versions of these packages would be brought in, and yarn would have to figure out what to do.
Yarn trying to make everyone happy lead to hoisting issues that lead to subtle bugs like these where a different React provider would be required in one place but not another:
In this release, we’ve removed @types/react
and @types/react-dom
from @redwoodjs/testing
which means your web side’s package.json is the source of truth.