Artwork: https://code-art.pictures/
Why migrate to wouter?
react-router adds about 30 kB (minified) to your bundle, while wouter requires less than 4 kB. Although the react-router team has made significant efforts in version 7 to optimize its bundle size, it still feels excessive if your primary task is simply switching between a few routes.
Moreover, implementing server-side rendering (SSR) with wouter is straightforward. In contrast, with react-router v7, SSR is only easy when you use it as a framework. If you prefer to use it as a library, the process is unclear since it's not documented — an omission that's both surprising and frustrating, to be honest.
Why stay with react-router?
react-router is a mature library with a large and active community. If your project involves complex routing scenarios, react-router is more likely to provide the tools and support you need.
Hint: If you decide to stick with react-router, be sure to upgrade from v6. Version 7 is about twice as efficient in terms of bundle size.
1. Updating deps to wouter
npm uninstall react-router react-router-dom
npm i wouter
If you're already on react-router v7, you probably don't have react-router-dom.
2. Updating Routes to Switch
- Update imports
- Change
<Routes>
to<Switch>
- In your routes, move elements from
element
property to<Route>
's children
Before
import { BrowserRouter, Route, Routes } from 'react-router'
function App() {
return (
<Routes>
<Route path='/' element={<Index/>} />
...
</Routes>
)
}
After
import { Route, Switch } from 'wouter'
function App() {
return (
<Switch>
<Route path='/'>
<Index/>
</Route>
...
</Switch>
)
}
3. Updating Links
Just update imports. wouter has the same API here
Before
import { Link } from 'react-router'
After
import { Link } from 'wouter'
4. Updating navigation
- Update imports
- Change
useNavigate()
touseLocation()
- Change
navigate()
tosetLocation()
Before
import { useNavigate } from 'react-router'
function MyComponent() {
const navigate = useNavigate()
function navToAbout() {
navigate('/about')
}
// ...
}
After
import { useLocation } from 'wouter'
function MyComponent() {
const [, setLocation] = useLocation()
function navToAbout() {
setLocation('/about')
}
// ...
}
5. Implementing SSR
I don’t know how to implement SSR with react-router v7 🙂 That’s why, in this step, we’ll implement it from scratch using wouter — it’s surprisingly simple. All you need to do is wrap your app in a <Router>
component:
entry-server.js
import { renderToString } from 'react-dom/server'
import { Router } from 'wouter'
function prerenderApp() {
return renderToString(
<Router ssrPath='/'>
<App />
</Router>
)
}
entry-client.js
import { hydrateRoot } from 'react-dom/client'
import { Router } from 'wouter'
hydrateRoot(
document.getElementById('app-root'),
<Router>
<App />
</Router>
)
We are done!
Now run your favorite bundle analyzer (e.g., webpack-bundle-analyzer or vite-bundle-visualizer) and enjoy the results!
Top comments (0)