Skip to content
Draft
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
31aad1d
refactor(router-core): Process routeTree into segment tree instead of…
Sheraff Nov 1, 2025
df389c6
foo
Sheraff Nov 1, 2025
23bacf4
bar
Sheraff Nov 1, 2025
f3236f2
PoC works
Sheraff Nov 1, 2025
627e017
faster
Sheraff Nov 1, 2025
dd1e3e3
faster
Sheraff Nov 1, 2025
e274212
remove node key, each object is a node
Sheraff Nov 2, 2025
baa2764
handle optional and wildcard
Sheraff Nov 2, 2025
bb4f022
there can be multiple wildcard children on a node because of prefix/s…
Sheraff Nov 2, 2025
adbcdd5
use index for skipping instead of the node itself
Sheraff Nov 2, 2025
8c886b8
fix node collision by param name only
Sheraff Nov 2, 2025
5b784fd
fix init of routesById and routesByPath
Sheraff Nov 2, 2025
9bf39da
some early tests
Sheraff Nov 2, 2025
484fc81
just comments
Sheraff Nov 2, 2025
e2339cc
use bitmask instead of array for skipped nodes during match
Sheraff Nov 2, 2025
f190778
start replacing in path.ts
Sheraff Nov 2, 2025
d6db54e
minor
Sheraff Nov 2, 2025
a60faa8
depth
Sheraff Nov 9, 2025
d15c9d9
fuzzy matching
Sheraff Nov 9, 2025
1a6a969
better sort function
Sheraff Nov 10, 2025
7c91a68
dynamic and optional matches use the stack
Sheraff Nov 10, 2025
4cd8726
no regex during matching yields 2x perf
Sheraff Nov 10, 2025
48f59ce
simplify interpolatePath and matchId
Sheraff Nov 10, 2025
c034ec2
Merge branch 'main' into refactor-router-core-process-route-tree-into…
Sheraff Nov 11, 2025
3fd5fd1
clean resolvePath
Sheraff Nov 11, 2025
54c14b9
optimize parseSegment
Sheraff Nov 11, 2025
4413339
support processing flat route tree for route masks matching
Sheraff Nov 11, 2025
82ae4d4
support routeMasks option as a flat tree
Sheraff Nov 11, 2025
ff17ea8
deprecate MatchRouteOptions 'caseSensitive' option
Sheraff Nov 11, 2025
88cd231
support deprecated single route match, slight performance penalty, st…
Sheraff Nov 11, 2025
56808aa
plug it into actual router
Sheraff Nov 11, 2025
14007cb
remove ai context
Sheraff Nov 11, 2025
a6f379c
ci: apply automated fixes
autofix-ci[bot] Nov 11, 2025
eb140cd
fix build
Sheraff Nov 11, 2025
162a3d7
ci: apply automated fixes
autofix-ci[bot] Nov 11, 2025
58baf3e
typos
Sheraff Nov 11, 2025
4dab29f
fix plugin HMR
Sheraff Nov 11, 2025
66a38b2
remove flatRoutes from devtools
Sheraff Nov 11, 2025
b40c320
wildcard suffix can include slashes
Sheraff Nov 11, 2025
3c10a6c
explore all branches before returning
Sheraff Nov 11, 2025
d20010e
some unit tests
Sheraff Nov 11, 2025
ba4cc90
hmr plugin prettify
Sheraff Nov 11, 2025
5f6236c
init route before processing
Sheraff Nov 11, 2025
3751534
more unit
Sheraff Nov 11, 2025
9f60967
remove commented out
Sheraff Nov 11, 2025
caa7fe1
_splat and *
Sheraff Nov 11, 2025
dfa98e9
prettier
Sheraff Nov 11, 2025
e518239
fix single match and flat match
Sheraff Nov 11, 2025
b8c1c2e
misc optims
Sheraff Nov 11, 2025
7e2ef5d
prettier
Sheraff Nov 11, 2025
58775f7
cache resolvePath
Sheraff Nov 11, 2025
bde9344
resolvePath: improve cache hit rate, add common path skips
Sheraff Nov 11, 2025
89bf3be
restore some matching tests
Sheraff Nov 12, 2025
cd9f4dc
restore some more tests
Sheraff Nov 12, 2025
8110b6e
update unit tests to new segment format (not a fix)
Sheraff Nov 12, 2025
92093b8
some segment parsing fixes
Sheraff Nov 12, 2025
f1a0b7d
fix curly-braced required param without prefix/suffix
Sheraff Nov 12, 2025
2c5d4b1
skipped params are not included at all in the params object
Sheraff Nov 12, 2025
f04d540
fix multi-segment wildcard suffix
Sheraff Nov 12, 2025
b8aead3
add failing match test
Sheraff Nov 12, 2025
3e26bcd
skipped optional nodes can match beyond the end of the path
Sheraff Nov 12, 2025
5c7e8c1
add failing case sensitivity test
Sheraff Nov 12, 2025
c6daad9
Merge branch 'main' into refactor-router-core-process-route-tree-into…
Sheraff Nov 12, 2025
bd59a1e
remove 2nd while loop, everything through the stack, bye bye performance
Sheraff Nov 12, 2025
cd8bd06
add cache to matching methods
Sheraff Nov 12, 2025
9f92e6b
fix build
Sheraff Nov 12, 2025
f3e5a80
fix fuzzy rest argument leading slash
Sheraff Nov 12, 2025
4b2df33
add more test cases
Sheraff Nov 12, 2025
0ca25b1
batch push in stack (will refactor, but at least this works)
Sheraff Nov 12, 2025
4647f9d
remove batch stack append, iterate backwards instead
Sheraff Nov 12, 2025
e9489e1
comments
Sheraff Nov 12, 2025
a46ce08
some more unit tests
Sheraff Nov 12, 2025
947b47e
add comment about skipped bitmask being limited to 32
Sheraff Nov 12, 2025
3785a2e
match wildcards beyond last segment
Sheraff Nov 12, 2025
435f4e9
remove deprecated test file
Sheraff Nov 12, 2025
c2342ef
Merge branch 'main' into refactor-router-core-process-route-tree-into…
Sheraff Nov 12, 2025
20c5b1f
wip test
Sheraff Nov 12, 2025
aafbcd3
include caseSensitivity in dynamic node sort function
Sheraff Nov 13, 2025
320cdbd
more unit tests
Sheraff Nov 13, 2025
896956e
code comment
Sheraff Nov 13, 2025
a30e03d
segments without text cannot be case-sensitive
Sheraff Nov 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions packages/router-core/src/Untitled-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

<main-question>
What are the different ways / data structures / algorithms to fullfil the following requirements?
</main-question>

<answer-expectations>
- all code should be javascript / typescript
- ask any questions you might need to answer accurately
- start by listing all the best approaches with a smal blurb, pros and cons, and I'll tell you which I want to delve into
- do NOT look at the existing codebase
</answer-expectations>

<routing-requirements>
A route is made of segments. There are several types of segments:
- Static segments: match exact string, e.g. 'home', 'about', 'users'
- Dynamic segments: match any string, e.g. '$userId', '$postId'
- Optional dynamic segments: match any string or nothing, e.g. '{-$userId}', '{-$postId}'
- Wildcard segments (splat): match anything to the end, must be last, e.g. `$`

Non-static segments can have prefixes and suffixes
- prefix: e.g. 'user{$id}', 'post{-$id}', 'file{$}'
- suffix: e.g. '{$id}profile', '{-$id}edit', '{$}details'
- both: e.g. 'user{$id}profile', 'post{-$id}edit', 'file{$}details'

In the future we might want to add more segment types:
- optional static segments: match exact string or nothing, e.g. '{home}' (or with prefix/suffix: 'pre{home}suf')

When the app starts, we receive all routes as an unordered tree:
Route: {
id: string // unique identifier,
fullPath: string // full path from the root,
children?: Route[] // child routes,
parentRoute?: Route // parent route,
}

When matching a route, we need to extract the parameters from the path.
- dynamic segments ('$userId' => { userId: '123' })
- optional dynamic segments ('{-$userId}' => { userId: '123' } or { })
- wildcard segments ('$' => { '*': 'some/long/path' })

When the app is live, we need 2 abilities:
- know whether a path matches a specific route (i.e. match(route: Route, path: string): Params | false)
- find which route (if any) is matching a given path (i.e. findRoute(path: string): {route: Route, params: Params} | null)

To optimize these operations, we pre-process the route tree. Both pre-processing and matching should be highly performant in the browser.
</routing-requirements>

<some-details>
- scale: we expect to have between 2 and 2000 routes (approximately)
- all routes are known at app start time, no dynamic route addition/removal
- memory is not an issue, don't hesitate to use more memory to gain speed
- routes can be nested from 1 to 10 levels deep (approximately)
- we have no preference for certain patterns, we are open to rewriting everything
- matching must be deterministic
- we always favor a more specific route over a less specific one (e.g. /users/123/profile over /users/$userId/$)
- each segment can be case sensitive or case insensitive, it can be different for each segment. We know this at pre-processing time.
- we cannot pre-process at build time, all pre-processing must happen at app start time in the browser
</some-details>
Loading