Redwood v7.0.0 Upgrade Guide

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:

:studio_microphone: 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.

:construction_worker_man: Heads up

If you don’t have a clean working directory, commit or stash your changes before running codemods—they can overwrite files!

:evergreen_tree: Arapaho Forest

This major version is part of the Arapaho Forest epochal version

Breaking Changes

Node.js v20

:zap: 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; remove engines.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:

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

:zap: 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:

  1. add "../node_modules/@testing-library" to typeRoots
  2. replace "@testing-library/jest-dom" with "jest-dom" in types

For example, here’s the difference in Create Redwood App’s web-side tsconfig.jsons 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

:zap: Quick summary

  • If you depend on more than just id and email being sent back to the client, you have to specify those fields in the new allowedUserFields 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 of authFields.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:

  1. 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.
  2. forgotPassword handler’s signature has changed, adding a second argument. Previously, a single user object was passed which would contain the resetToken to be emailed to the user. Since we’re now removing everything that isn’t in the allowedUserFields 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 the user 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

:zap: Quick summary

  • yarn rw serve now behaves more like dev by serving the web and api side on separate ports
  • yarn 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 new api/src/server.ts file using yarn 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

:zap: 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.

15 Likes

Seems to work so far.

I had to remove my server.config.js, it seems to have been created with the project back when it was created. And the docker we deploy currently has both web and api in one process.

Bummer, that it’s still not prettier 3 as we’re still stuck on prettier-plugin-tailwindcss 0.4 due to that

4 Likes

I know! :sob:

There’s a tiny bit of more info here

Hi,

First of all many thanks to @Tobbe for the Prisma Bytes’ PR.

Is there any plan to update the Redwood scaffolding CLI yarn rw g scaffold ... to handle with a really basic mechanic download and upload of bytes files instead of [object object] rendering? Or at least display it’s Base64/Raw equivalent like the dbStudio does?

Hi @matbgn - that’s an interesting idea.

What might that look like? If you were to manually modify that Edit Page (and the View one) to do as you suggest, what would the code look like? Or, even a mock up? Would there be a html file input?

There is the ability to eject the current generator templates (see: Command Line Interface | RedwoodJS Docs) and then modify them locally to have some custom behavior.

That might be a first step to implementing such a new feature.

If you do have some examples of what that feature might be, an RFC as a new GitHub issue is most welcome!

1 Like

I upgraded to the RC and I think I followed the manual instruction correctly. However, now when I run yarn rw type-check api, I see

Found 277 errors in 2 files.

Errors  Files
   259  ../node_modules/fastify/types/instance.d.ts:204
    18  ../node_modules/fastify/types/route.d.ts:135

Any ideas what’s going on?

Hey @aoifelee, thanks for trying out the RC! Haven’t seen that one just yet, is there any more information to the errors? I’ll also refresh my memory if it’s common to see errors in node_modules for tsc but I wouldn’t think it would be

Hey @dom - no I’ve never seen node_module errors reported before. Here’s the first couple lines in the output:

✔ Generating the Prisma client...
✔ Generating types
../node_modules/fastify/types/instance.d.ts:204:5 - error TS1139: Type parameter declaration expected.

204     const SchemaCompiler extends FastifySchema = FastifySchema,
        ~~~~~

../node_modules/fastify/types/instance.d.ts:204:26 - error TS1005: ',' expected.

204     const SchemaCompiler extends FastifySchema = FastifySchema,

Let me know if there’s any other info that would help.

I can’t quite reproduce yet. Here are some relevant stats about my project:

  • Redwood v7 RC version: 7.0.0-rc.970 (may also look like 7.0.0-rc.970+2b404570e)
  • fastify version: 4.25.2
  • typescript version: 5.3.3

I had a look in node_modules at the file and line that you’re getting an error on. Mine looks the same I think:

  route<
    RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
    ContextConfig = ContextConfigDefault,
    const SchemaCompiler extends FastifySchema = FastifySchema,
  >(opts: RouteOptions<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;

Have you tried the ol’ delete node_modules and re-install trick? That and yarn dedupe sometimes get rid of these phantom errors.

This RC did require a slight edit to the web/tsconfig.json—possible you made more edits than necessary there? Or maybe your project has other tsconfig.json settings mine doesn’t? All good if not, just trying to think of things that could be at play.

I have the same versions and, yeah, that looks like the same source. Deleting node_modules and yarn dedupe didn’t have any effect.

I double checked, and it looks like I only made the suggested changes to tsconfig.json in the upgrade guide, and in general I think I’ve basically followed whatever RW generated / suggested in previous upgrades.

For what it’s worth, it seems like the runtime behavior is fine - I just find it helpful to put type-check into CI. Anyway, I’ll try again to isolate the cause of the change tomorrow.

1 Like

Thanks for the reply @dthyresson I put it on my plate :+1:

In the mean time if someone has a related proposition don’t hesitate.

Okay, never mind :slight_smile:. I actually did have an old version of Typescript in the package.json of a sibling, non-RW workspace. So, not a RW issue.

Sorry for the noise - congrats on the new release, looking forward to it.

1 Like

No worries glad you figured it out! And not noise at all, someone may have the same problem. So hard to keep track of all these node_modules sometimes. :sob:

Hey Everyone,

Is Studio supposed to work with this release? When I try to yarn rw studio I get the following error:

The studio command requires Redwood version 7.0.0-canary.889 or greater, you are using 7.0.0-rc.988.

I am getting this same issue when trying to run the studio.

Hi @Andre and @EverydayTinkerer - sorry for those troubles.

We want to keep the version of Studio in-sync with the version of Redwood – which is why Studio checks that it’s the same version.

Seems Studio npm publishing may be out of sync with the canary builds of v7.

Instead of using the rc, could you upgrade your project to a canary release instead?

yarn rw upgrade --tag=canary

Please let me know if that works.

@Andre and @EverydayTinkerer, this issue was specific to the RC. I just released v7 and it seems to work locally now for me. Mind upgrading to the real thing and giving it another try?

Wow that’s great news! I will certainly do that and report back. Thanks a lot @dom and @dthyresson!

Hi @dom and @dthyresson happy to share that Studio works like a charm with v7.

2 Likes