Before we get started, just in case you missed them, here are quick links to the announcement post and Changelog:
First run the upgrade command, then we’ll go through all the breaking changes one by one:
yarn rw upgrade
Heads up
If you don’t have a clean working directory, commit or stash your changes before running codemods—they can overwrite files!
Breaking changes
- Vite
- Prisma v5
- Storybook v7
- Suspense Router
RedwoodApolloProvider
’s link prop- Firebase major versions
- SuperTokens major versions
Vite
In Redwood v6, all projects use Vite by default.
if you’re not ready to migrate to Vite yet, you can switch back to Webpack via the bundler
key in your project’s redwood.toml
file:
[web]
+ bundler = "webpack" # 👈 New bundler key
port = 8910
apiUrl = "/api"
includeEnvironmentVariables = ["CONTEXT", "NODE_ENV", "DEPLOY_ID"]
title = "My Redwood App"
Even if you switch back to Webpack, we still recommend running through all the changes here. We plan to remove Webpack support in a future major, but won’t do so till we see strong adoption metrics.
Without further ado, let’s set up Vite:
yarn rw setup vite
Wait—are you an existing Vite user?
If you opted into Redwood’s experimental Vite support in the last couple releases (thank you!), you’ll have to make these changes instead of setting up Vite again:
- The entry point is now
entry.client.{jsx,tsx}
instead ofentry-client.{jsx/tsx}
@redwoodjs/vite
is a dev dependency, instead of a dependency . Take a look at the package.json in the template for referenceBe sure to follow the rest of the guide!
This command
- adds the entry point,
web/src/entry.client.{jsx,tsx}
- adds Vite’s config file,
web/vite.config.{js,ts}
- adds
@redwoodjs/vite
as a dev dependency to the web workspace
Here’s a short description of the new files:
File | Description |
---|---|
web/src/entry.client.{jsx,tsx} |
Your project’s entry point. This file was previously hidden; it’s where you’ll see React mount to the DOM. Vite starts bundling from here. |
web/vite.config.{js,ts} |
Vite’s config file. Redwood’s config is just a Vite plugin. |
1. Update the DevFatalErrorPage
Codemod Available
To implement this step via automated codemod, run:
npx @redwoodjs/codemods update-dev-fatal-error-page
Heads up
This will replace your
FatalErrorPage
. If you’ve customized it, you may want to do this manually. Keep reading, it’s easy!
With Vite, require
statements are no longer supported. You’ll need to replace them with import
or await import
statements.
Most Redwood apps have at least one require
statement, in web/src/pages/FatalErrorPage.{js,tsx}
:
// web/src/pages/FatalErrorPage.{js,tsx}
// ...
// Ensures that production builds do not include the error page
let RedwoodDevFatalErrorPage = undefined
if (process.env.NODE_ENV === 'development') {
RedwoodDevFatalErrorPage =
require('@redwoodjs/web/dist/components/DevFatalErrorPage').DevFatalErrorPage
}
This won’t work anymore, so either run the codemod above or replace the require
statement:
// web/src/pages/FatalErrorPage.{js,tsx}
// ...
- let RedwoodDevFatalErrorPage = undefined
- if (process.env.NODE_ENV === 'development') {
- RedwoodDevFatalErrorPage =
- require('@redwoodjs/web/dist/components/DevFatalErrorPage').DevFatalErrorPage
- }
+ import { DevFatalErrorPage } from '@redwoodjs/web/dist/components/DevFatalErrorPage'
- export default RedwoodDevFatalErrorPage ||
+ export default DevFatalErrorPage ||
(() => (
<main>
...
</main>
))
2. Change all files using JSX with the .js
extension to .jsx
Using TypeScript?
If your project is 100% TypeScript, you can probably skip this step—.
tsx
files remain unchanged.
Codemod Available
To implement this step via automated codemod, run:
npx @redwoodjs/codemods convert-js-to-jsx
We’re deprecating the use of JSX syntax in .js
files. While files with the .js
extension will still work, you’ll be missing out on features like fast refresh.
If you have a JS file that doesn’t have JSX, its extension doesn’t need to change. Only those with JSX do.
3. Changes to how process.env
is used
Codemod Available
To implement this step via automated codemod, run:
npx @redwoodjs/codemods process-env-dot-notation
In v6, there are differences in the way environment variables are loaded:
-
If you’re receiving an error in the browser like
"process is undefined"
, it means that you…a. haven’t included the environment variable in your project’s
redwood.toml
fileb. haven’t prefixed it with
REDWOOD_ENV_
c. just don’t have it defined in one of your
.env
files at all
# redwood.toml
[web]
bundler = "vite"
includeEnvironmentVariables = [
"BAZINGA", # 👈 Make sure it's included here
]
#...
- Access
process.env
with dot notation
You can no longer access environment variables using array syntax, like process.env['MY_ENV_VAR']
. To fix this, use dot notation:
- process.env['MY_ENV_VAR']
+ process.env.MY_ENV_VAR
4. Using SVGs as components
If you’re importing directly from SVG files and using them as components, you’ll need to update your code in one of a few ways (detailed below)—we’re dropping support for it in this release.
By importing directly from SVG files, we mean like this:
// web/src/components/MyComponent/MyComponent.jsx
import Icon from './icon.svg' // 👈 Directly imported from the SVG file
const MyComponent = () => {
return (
<Button>
<Icon/> {/* 👈 Used as a component here */}
</Button>
)
}
You have a couple options:
- convert your SVGs to React components. To do that, you can use this codemod, or follow the instructions in Redwood’s docs: Assets and Files | RedwoodJS Docs
Codemod Available
To implement this step via automated codemod, run:
npx @redwoodjs/codemods replace-component-svgs
- if you are not styling your SVGs directly, you can also use an
<img>
tag:
import icon from './myIcon.svg'
const MyComponent = () => {
return (
<Button>
<img src={icon} alt="..."/> {/* 👈 Pass the url to the img's src attribute */}
</Button>
)
}
- add the SVGR plugin: vite-plugin-svgr - npm (SVGR was the plugin we used with Webpack to make these kind of imports work)
5. Use globalThis
instead of global
Codemod Available
To implement this step via automated codemod, run:
npx @redwoodjs/codemods change-global-to-global-this
Webpack polyfills the legacy Node.js global
object. As it’s not part of the ECMAScript language specification, Vite doesn’t, which means all instances of global have to be changed to globalThis
.
6. Static assets in the public folder are now served from /
instead of /public
With Webpack, you probably referred to static assets in the web/public
folder using URIs starting with /public/...
:
/* web/src/index.css */
@font-face {
font-family: 'My font';
src: url('/public/fonts/my-font.woff2') format('woff2'); /* 👈 URI starts with "/public" */
}
Vite serves them at /
instead. Just remove /public
from the URIs and everything should work again:
/* web/src/index.css */
@font-face {
font-family: 'My font';
- src: url('/public/fonts/my-font.woff2') format('woff2');
+ src: url('/fonts/my-font.woff2') format('woff2');
}
7. Update Mantine and Chakra UI config
Codemod Available
To implement this step via automated codemod, run:
npx @redwoodjs/codemods update-theme-config
If you’re using Mantine or Chakra UI, you’ll need to update how these libraries are configured. You may see an error like this in your browser’s console:
Uncaught ReferenceError: module is not defined
To fix this, you’ll need to make sure you’re not using module.exports
in your web/config/mantine.config.{js,ts}
or web/config/chakra.config.{js,ts}
files. The change is simple:
// web/config/{mantine,chakra}.config.{js,ts}
- module.exports = // Your theme...
+ const theme = // Your theme...
+ export default theme
8. Web workers require type: "module"
Vite outputs ESM. Depending on the web APIs you’re using, you may have to make some changes to configure them to work with ESM. One example is Web Workers. Web Workers default to the "classic"
type, which don’t understand ESM syntax like import
.
Usually the change is as simple as adding something like type: "module"
to the API’s configuration object:
// web/src/pages/WebWorkerPage/WebWorkerPage.tsx
const WebWorkerPage = () => {
- const myWorker = new Worker("worker.js");
+ const myWorker = new Worker("worker.js", { type: "module" });
// ...
Prisma v5
This major version of Redwood includes Prisma v5. Going along with the theme of this release, Prisma v5 has many changes that improve its performance, especially in serverless environments.
The breaking changes in Prisma v5 are relatively niche; for completeness, see Prisma’s upgrade guide linked below, but we don’t anticipate you having to make many changes if any are necessary at all:
Storybook v7
Storybook still uses the Webpack builder internally
As of v6.0.0, even if your project uses Vite, Storybook still uses the Webpack builder. We plan to ship the Vite builder for Storybook shortly, in a future minor, but couldn’t get it working in time for this release.
But the thing to watch out for here is that if you customize your project’s Vite config, it won’t apply to Storybook.
In this major, we’ve upgraded to Storybook v7 and decoupled it from the framework.
Most of the breaking changes in Storybook v7 were internal to the framework, but depending on the extent to which you use Storybook and its community addons, your results may vary. Here’s what we know for sure:
- Storybook removed the ability to configure the manager, which is the UI. If you were configuring the manager via the
web/config/storybook.manager.js
file, you’ll have to delete the file—Storybook won’t load it anymore. - If you use MDX stories, you’ll have to upgrade them to MDX v2. Refer to Storybook’s migration guide here: Docs | Storybook.
- For TypeScript projects, the
ComponentMeta
type from@storybook/react
is deprecated in favor of theMeta
type. Thecsf-2-to-3
codemod below updates it for you.
While it’s optional, we recommend upgrading your stories to Component Story Format 3. It’s fully backwards compatible and Storybook includes a codemod for it:
npx storybook@next migrate csf-2-to-3 --glob="web/**/*.stories.{js,tsx}"
One thing you’ll notice when you start Storybook for the first time after upgrading to Redwood v6 is that the Redwood CLI will install the @redwoodjs/cli-storybook
package:
$ yarn redwood storybook
Installing plugin "@redwoodjs/cli-storybook"...
Storybook is quite large and not everyone who uses Redwood uses it, so we’ve decoupled it from the CLI and made it a plugin so that it installs lazily, the first time you use it. We intend to do this with more commands to make Redwood leaner out of the box.
Suspense Router
We refactored the Router to use Suspense under the hood. For most, this refactor will largely go unnoticed. But there’s a subtle breaking change: components that aren’t Router components (Route
, Set
, and Private
) won’t be rendered anymore.
The only place you could’ve put a component like this was in a Set
, like this:
// web/src/Routes.tsx
//...
const Routes = () => {
return (
<Router>
<Set>
<MyCustomReactProvider> {/* 👈 This provider should be in the `Set`'s `wrap` prop */}
<Route path="/my-route" page={MyPage} name="myPage" />
</MyCustomReactProvider>
</Set>
<Route path="/" page={HomePage} name="home" />
<Route notfound page={NotFoundPage} />
</Router>
)
}
The fact that you could do this wasn’t intentional and was an artifact of the way the Router was written. Redwood always meant for these kinds of components to be in the Set
’s wrap
prop, like this:
- <Set>
- <MyCustomReactProvider> {/* 👈 This provider should be in the `Set`'s `wrap` prop */}
+ <Set wrap={MyCustomReactProvider}>
We added an ESLint rule in v5.4.0 to help you identify this problem. In this major, that rule will error instead of warn:
Having linting issues? If you haven’t yet, try restarting the ESLint server. If you’re using VS Code, you can do this by opening the Command Palette and typing in “ESLint: Restart ESLint Server”.
RedwoodApolloProvider’s link prop
Are you customizing
RedwoodApolloProvider
’s Apollo Link?If you don’t customize
RedwoodApolloProvider's
Apollo Link at all, you can skip this step.
The RedwoodApolloProvider
in web/src/App.{jsx,tsx}
takes a prop called graphQLClientConfig
:
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'
// ...
const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
<RedwoodApolloProvider
graphQLClientConfig={{ ... }} {/* 👈 Customize the Apollo Client instance */}
>
<Routes />
</RedwoodApolloProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)
export default App
It’s basically the same as Apollo Client’s config, with some special handling for a few props. One of those props is link
, which is the Apollo Client instance’s link.
If you wanted to customize it, it was cumbersome. If you weren’t adding a link to the very front of the array, you had to know the order of the links, which basically meant reading the source. In this major, A contributor added a better API: the argument passed to link
is now an array of objects with names instead of just an array of links.
Here’s an example of a console link before and after:
const link = (redwoodApolloLinks) => {
const consoleLink = new ApolloLink((operation, forward) => {
console.log(operation.operationName)
return forward(operation)
})
- return ApolloLink.from([consoleLink, ...redwoodApolloLinks])
+ return ApolloLink.from([consoleLink, ...redwoodApolloLinks.map(({ link }) => link)])
}
- feat(apollo): add linkFactory for better customization of apollo links by russell-dot-js · Pull Request #8500 · redwoodjs/redwood · GitHub
- chore(apollo): make previous Apollo Link change breaking by jtoar · Pull Request #8761 · redwoodjs/redwood · GitHub
Firebase major versions
For Firebase users, firebase
(used on the web side) and firebase-admin
(used on the api side) have released major versions v10 and v11 respectively. To upgrade, we didn’t have to make any changes besides upgrading the packages’ versions, but as always, the ease of upgrading will ultimately depend on your use of firebase. Please refer to the packages’ release notes:
- firebase-js-sdk/packages/firebase/CHANGELOG.md at main · firebase/firebase-js-sdk · GitHub
- Release Firebase Admin Node.js SDK v11.0.0 · firebase/firebase-admin-node · GitHub
There’s one important thing to note: the version of firebase-admin
in your project must be the same as Redwood’s version ( v11.10.1):
// api/package.json
{
"name": "api",
"version": "0.0.0",
"private": true,
"dependencies": {
"@redwoodjs/api": "v6.0.0",
"@redwoodjs/auth-firebase-api": "v6.0.0",
"@redwoodjs/graphql-server": "v6.0.0",
- "firebase-admin": "10.x.x"
+ "firebase-admin": "11.10.1"
}
}
Supertokens major versions
For SuperTokens users, SuperTokens has released a few major versions of supertokens-node
and a few minor versions of supertokens-auth-react
(which are breaking because it’s not v1). To upgrade, we recommend re-running the setup command:
yarn rw setup auth supertokens -f
One troubleshooting note: if you’re running into errors during dev after upgrading, we recommend clearing your browser’s application storage.
For more details about these majors and minors, see the supertokens-node
release notes (look for v13 to v15) and the supertokens-auth-react
release notes (look for v0.33 to v0.34).