docs: wip react-router migration guide
Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: blam <ben@blam.sh> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
---
|
||||
id: read-router-stable-migration
|
||||
title: react-router stable migration
|
||||
description: Guide for how to migrate from react-router beta to react-router 6 stable
|
||||
---
|
||||
|
||||
Backstage has for a long time been using `react-router` version `6.0.0-beta.0`. We adopted this unstable
|
||||
version because v6 had some new and features that fit really well with Backstage, particularly relative routing.
|
||||
Because we jumped on this early and unstable version, we knew that we would at some point need
|
||||
a breaking migration to the stable version of `react-router` v6, which is the point we're at now!
|
||||
|
||||
This migration is required but controlled by each app, meaning that you choose when you want
|
||||
to migrate your app. There will however be some point in the future where we drop support for the
|
||||
beta version of `react-router`, at which point you would be forced to migrate.
|
||||
|
||||
The stable version of React Router v6 brings a number of improvements and bug
|
||||
fixes. Notably, the way that paths are resolved has been improved, which fixes a
|
||||
bug where paths like `/catalog` and `/catalog-import` could get confused.
|
||||
|
||||
## Migration
|
||||
|
||||
### Step 1 - Upgrade to Backstage 1.6
|
||||
|
||||
The first Backstage release to support `react-router` v6 is `1.6`. You should upgrade to this version first before you start migrating. If you are an early bird and want to try out migration before that release, it is also shipped in `1.6.0-next.1`.
|
||||
|
||||
### Step 2 - Move `react-router` to `peerDependencies`
|
||||
|
||||
It's important that only one version of `react-router` is installed in the project at a time. Similar to how the `react` version
|
||||
is handled, all plugins and packages now declare a peer dependency on the React Router dependencies, rather than a direct dependency.
|
||||
The only exception to this is the app package, which has the direct dependencies that end up deciding what version of React Router that
|
||||
you are using in your project.
|
||||
|
||||
Your internal packages might specify a dependency on `react-router` or `react-router-dom` in their `package.json` and important that those are converted to `peerDependencies` so we can control the version of `react-router` in the app `package.json`.
|
||||
|
||||
You can automate this step by running the following command:
|
||||
|
||||
```bash
|
||||
yarn backstage-cli migrate react-router-deps
|
||||
```
|
||||
|
||||
For those interested in doing this manually, apply the below change to all `package.json` files except the one in the app. Skip moving any dependencies that don't already exist, and move both `dependencies` and `devDependencies`.
|
||||
|
||||
```diff
|
||||
dependencies {
|
||||
...
|
||||
- "react-router-dom": "^6.0.0-beta.0",
|
||||
- "react-router": "^6.0.0-beta.0"
|
||||
},
|
||||
peerDependencies: {
|
||||
...
|
||||
+ "react-router-dom": "6.0.0-beta.0 || ^6.3.0",
|
||||
+ "react-router": "6.0.0-beta.0 || ^6.3.0"
|
||||
},
|
||||
```
|
||||
|
||||
### Step 3 - Ensure that your external plugins are updated
|
||||
|
||||
It's important that you also update your external plugins to their latest version as these will have to perform the same `peerDependencies` update.
|
||||
|
||||
During this migration there may be external plugins that need updating. If you encounter any plugins outside of the `@backstage` scope that are incompatible with your installation, make sure to check for an existing issue or raise a new one at the plugin's GitHub repository.
|
||||
|
||||
### Step 4 - Bump the React Router dependencies in your app.
|
||||
|
||||
Now it's time to do the actual migration to the latest version of React Router. At this time of writing that is `6.3.0`, but that is of course a moving target.
|
||||
|
||||
The first step is to modify `packages/app/package.json`:
|
||||
|
||||
```diff
|
||||
- "react-router": "6.0.0-beta.0",
|
||||
- "react-router-dom": "6.0.0-beta.0",
|
||||
+ "react-router": "^6.3.0",
|
||||
+ "react-router-dom": "^6.3.0",
|
||||
```
|
||||
|
||||
In case you happen to have multiple app packages in your project, apply the same change to all those packages.
|
||||
|
||||
Once the change has been made, run `yarn install`, and then `yarn why react-router` to validate the installation. You should see the following line in the log as the only resulting entry:
|
||||
|
||||
```
|
||||
=> Found "react-router@6.3.0"
|
||||
```
|
||||
|
||||
If you see multiple entries, and especially `=> Found "react-router@6.0.0-beta.0"`, then your dependencies have not yet been fully migrate to support React Router v6 stable. Double check the steps above, using the information that the Yarn `why` command logged. Repeat the same process for `yarn why react-router-dom`.
|
||||
|
||||
If you end up being stuck not being able to move your entire project your entire project to stable versions cleanly, then you can use Yarn `"resolutions"` overrides in your root `package.json`. Try to avoid this option as it may lead to hidden breakages at runtime, and verify any plugins that needed the override. A better option is likely to hold off migrating for a while until plugins have had time to be updated.
|
||||
|
||||
### Step 5 - Breaking Changes
|
||||
|
||||
For a new app created with `npx @backstage/create-app`, the above steps are all you need to do. That may not be where you are at though, having created many internal plugins and customizations. Review the breaking changes in the [React Router changelog](https://reactrouter.com/docs/en/v6/upgrading/reach#breaking-updates) and validate all parts of your app. We've summarized the most important breaking changes below.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
See [changelog](https://reactrouter.com/docs/en/v6/upgrading/reach#breaking-updates) for a full list of breaking changes. Below we highlight a couple of most important ones.
|
||||
|
||||
PermissionedRoute
|
||||
|
||||
### Route paths
|
||||
|
||||
Absolute route paths within each `Routes` element must now match their own location, meaning that the following is invalid:
|
||||
|
||||
```tsx
|
||||
<Routes>
|
||||
<Route path="/foo">
|
||||
<Route path="/bar" /> {/* INVALID, must be "/foo/bar" or "bar" */}
|
||||
</Route>
|
||||
</Routes>
|
||||
```
|
||||
|
||||
The most common case where this will cause breakages in the `EntityPage`s, which is covered in the above migration steps. But this change may also cause breakages in plugins as well.
|
||||
|
||||
<how the route paths broke>
|
||||
|
||||
### Routes and Route components
|
||||
|
||||
The `Routes` and `Route` component both received a large related breaking changes. It is no longer possible
|
||||
to have anything but `Route` elements and React fragments be a child of a `Routes` element. This means that
|
||||
structures like these:
|
||||
|
||||
```tsx
|
||||
<Routes>
|
||||
<Navigate key="/foo" to="/bar" />
|
||||
...
|
||||
</Routes>
|
||||
```
|
||||
|
||||
need to be migrated to this:
|
||||
|
||||
```tsx
|
||||
<Routes>
|
||||
<Route path="/foo" element={<Navigate to="/bar" />} />
|
||||
...
|
||||
</Routes>
|
||||
```
|
||||
|
||||
Somewhat related to the `Routes` change, it is no longer possible to render a
|
||||
`Route` element by itself, outside of a `Routes` wrapper. Previously, rendering
|
||||
such a `Route` element would cause the contents of its `element` prop to be
|
||||
rendered instead, but now it will throw an error.
|
||||
|
||||
### NavLink
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
Use console
|
||||
|
||||
Check yarn.lock for packages depending on older versions of react-router
|
||||
|
||||
```bash
|
||||
grep 'react-router-dom "6.0.0-beta.0"' yarn.lock
|
||||
```
|
||||
|
||||
^ do we have to support ranges as well? maybe not
|
||||
Reference in New Issue
Block a user