Building my own router
Tags: react, javascript, showdev
Published: 2020-08-26 22:50:00

I don't want to use `react-router` on my personal projects. Mostly because of the bloat you incur for the high degree of compatibility (even the shiny version 6 still has a fair amount of cruft).

I looked at alternatives, but truth be told, no one really wants to reinvent the wheel, and for good reasons! It works, and Facebook is probably a bigger issue if we're talking ethics. But hey, it's nonetheless a fun exercise to get acquainted with what browsers can do nowadays.

### It's about leaving things behind

`react-router` relies on their own `history` package, because it wants to be compatible with react native and Internet Explorer. I do not need nor want that, so there are a fairly consequential number of wins to be had just there. Though there's a gotcha: the history API can drive events in specific cases, but you'll still need some wrapping in the cases an event is not fired.

### One way to do things

`react-router` affords you flexibility, as it's not opinionated in how you build your routes, but that means that different codebases can look very different. I often need to jump projects at work, and the lack of consistency due to that freedom is a curse I'd rather not deal with. Having a single way to do things is simpler to explain and learn, simpler to use, and simpler to maintain.

## Introducing `itsy-bitsy-router`

An evergreen-browser barebones routing solution that only offers a hook-based API, and a `Link` component for convenience. There's a [documentation website](https://itsy-bitsy-router.netlify.app) available to get started quickly, and while it's not expansive yet, it does the job quite well, and allows me to dog-food the router with just itself.

### Features

I went with a very familiar API. It works, and does the job in a very simple manner. It supports url matching the way you'd expect: `path/to/:match/`. It's fairly simple to use, and should cater to most use-cases! If not, that's probably something that can be improved, and [opening an issue](https://github.com/synecdokey/itsy-bitsy-router/issues) could make a difference.

It's also really lightweight, at [around 1kb gzipped](https://bundlephobia.com/result?p=itsy-bitsy-router@0.2.2). This is especially valuable when considering that a router is going to be part of your initial payload no matter what.

### Limitations

- As `history.pushState()` and `history.replaceState()` do not fire any events, we need the `useNavigate()` hook to handle navigation in places where `Link` is not desirable. `history.forward()` and `history.back()` do work and trigger
rerenders as expected though.
- TypeScript can't really play nice with something like `useParams()`, and probably never will. So we're stuck with `Record<string, string>` as the return type, instead of having something that relates to the current component. I don't see an easy way out of this one given we rely on string-defined properties with the `/path/to/:id` API pattern. There may be an alternative API, focused on Typescript to be found at some point, but one of the selling points right now is to enable a quick opt-in/opt-out.
- SSR is something that probably doesn't work as-is (Maybe?), haven't really tried. But with gatsby and next already equipped with their own routing, I'm not really willing to spend time investigating this.
- There's no support for React Native. That's definitely not something I need, and I want to keep things as lean as I can.

## What's next

I want to get a feel for the API as it is, and maybe adjust a few things along the way, but this should be fairly final. The one thing I really want to integrate before cutting a v1 is React's Concurrent Mode, as routing is one of the rare occasions where it really shines.

I mainly did this for myself, and for fun, but I feel like this could go further than that! If you liked it, do let me know ✨