Build Your Own Router with URLPattern()
39 points
by tobr
4 days ago
| 6 comments
| jschof.dev
| HN
jslakro
1 minute ago
[-]
Page.js is a good alternative for a client-side router https://visionmedia.github.io/page.js/
reply
pscanf
1 hour ago
[-]
I've done something similar in a React project I'm working on to avoid dealing with the insanity that is react-router.

Call me naïve, but routing in a single page application is just not that hard of a problem. At the core it's about having a piece of state¹ (your active route) which determines which part of the app you want to render–something you can do with a switch statement². On top of that, you want to synchronize that state to the page URL³.

Doing it yourself requires more boilerplate code, no question about it. But it's not that much code tbh (not very complex either), and you get back control over that important piece of state, which otherwise remains opaque and difficult to work with–i.e., its "shape" is pre-determined by the routing library you use. For example, react-router doesn't support parallel routes.

¹ https://github.com/superegodev/superego/blob/main/packages/a...

² https://github.com/superegodev/superego/blob/main/packages/a...

³ https://github.com/superegodev/superego/blob/main/packages/a...

reply
embedding-shape
36 minutes ago
[-]
I also basically re-invent a tiny 50 line router for every web project. Hardly ever go beyond "Map URL -> Page" and "Map URL + Parameters -> Page with properties", and when you do, knowing 100% how it works helps a lot.

I also agree it isn't a hard problem, but personally I'd say you got the flow the wrong way around. You don't want to "synchronize state to the page URL" but rather treat the page URL as something you create state from, so it works both when you navigate there by pressing anchor tags, or the user manually enters the URL, and it gets a bit easier to manage.

Basically, URL is the top-level state, and from there you derive what page, then render that page, rather than the other way around.

reply
simon04
20 minutes ago
[-]
A very tiny router is provided by nanostores: https://github.com/nanostores/router
reply
sampullman
38 minutes ago
[-]
I don't think it's naive, I often do the same in Vue. A pretty useful subset of vue-router can be implemented in less than a tenth of the bundle size.
reply
tinco
35 minutes ago
[-]
This seems really irrelevant to the browser. I wonder why this was standardized, JavaScript is easily powerful enough to express this. Surely it hasn't been a performance bottleneck for it needing a native api?

I agree with the other two comments, surely almost every frontend webdev has implemented a router in their career unless they never strayed from the major frameworks. It's really not a complicated thing to have to build. I'm not one to look a gift horse in the mouth but I don't see why we're being given this one.

reply
embedding-shape
33 minutes ago
[-]
Anytime I end up wondering "Why do we have feature X on the web?" I tend to up end reading through proposals and I always end up finding a suitable answer that makes me wonder no more. For this specific feature, there is lots of prior discussions about why this is needed in the first place here: https://github.com/whatwg/urlpattern
reply
kemayo
13 minutes ago
[-]
Based on https://github.com/whatwg/urlpattern/blob/main/explainer.md it looks like they specifically wanted it as a way to scope service workers so it's easy to make them only run on certain parts of a site, and viewed giving people something easy to use for other URL matching as a nice bonus.
reply
jazzypants
54 minutes ago
[-]
Is this really that much easier than matching paths and query strings yourself? I'm glad that there is an official API now, but this article didn't really show me anything to get excited about as someone who has built several client-side routers from scratch.
reply
bob1029
33 minutes ago
[-]
Writing a fast router can be surprisingly difficult if you are trying to cover the edges. The state of the art is not trivial:

https://github.com/dotnet/aspnetcore/blob/main/src/Http/Rout...

reply
jazzypants
26 minutes ago
[-]
You're assuming that URLPattern is performant... That doesn't seem to be the case currently.

https://adventures.nodeland.dev/archive/you-should-not-use-u...

https://github.com/denoland/deno/issues/19861

reply
embedding-shape
29 minutes ago
[-]
The thing is, performance in that particular context hardly matters, unless you're forcing users to switch pages faster than 1 page per second. Even if each resolving takes 0.1 seconds (which be bad, don't get me wrong), 99% of users wouldn't notice a thing, and if you're a small agency/shop/company/team, focusing on more general things tends to be time spent better.
reply
teddyh
1 hour ago
[-]
SPA router, not IP router.
reply
embedding-shape
35 minutes ago
[-]
Kind of obvious when a DOM/Web API is mentioned, isn't it? Besides, does it really matter? Same ideas you use for building a frontend router can be used to build a backend router, and vice-versa.
reply
simon04
27 minutes ago
[-]
Maybe not so much for an Internet Protocol router?
reply
jauntywundrkind
22 minutes ago
[-]
I'm really glad we have URLPattern, as it's a fairly mundane task that shouldn't need us to bring in special tools. I can't imagining argue that the plarform shouldn't come well equipped for basic cases like this. Ideally a native implementation will be able to use SIMD and be faster too, which is a nice to have.

Unfortunately cases like here in the article are an example of why URLPattern had enormous push back during development. It's not the worst thing in the world to run three or four patterns one after another. But generally, doing a linear search for the right pattern doesn't scale well at all! If there's a dozen routes, running pattern after pattern is probably not ideal!

We can look at Hono routers, for example. Which has a bunch of different examples, most of which will one-shot a bunch of patterns at once. RegExpRouter, TrieRouter. There's good write-ups for the tradeoffs across them. But they all take a bunch of routes up front, and combine them into a single matcher, attempting to re-use work across patterns. https://hono.dev/docs/concepts/routers

Really good we have URLPattern, but this is the anti-use-case, that almost convinced folks not to make URLPattern at all.

reply