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 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 could make a difference.
It's also really lightweight, at around 1kb gzipped. 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()
andhistory.replaceState()
do not fire any events, we need theuseNavigate()
hook to handle navigation in places whereLink
is not desirable.history.forward()
andhistory.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 withRecord<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 ✨
Top comments (0)