Skip to content

Commit 627e017

Browse files
committed
faster
1 parent f3236f2 commit 627e017

File tree

1 file changed

+39
-28
lines changed

1 file changed

+39
-28
lines changed

packages/router-core/src/new-process-route-tree.ts

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,25 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
136136
const value = path.substring(data[2]!, data[3])
137137
switch (kind) {
138138
case SEGMENT_TYPE_PATHNAME: {
139-
const name = caseSensitive ? value : value.toLowerCase()
140-
const existingNode = node.static?.find(s => s.caseSensitive === caseSensitive && s.name === name)
141-
if (existingNode) {
142-
nextNode = existingNode.node
139+
if (caseSensitive) {
140+
const existingNode = node.static?.get(value)
141+
if (existingNode) {
142+
nextNode = existingNode
143+
} else {
144+
node.static ??= new Map()
145+
nextNode = {}
146+
node.static.set(value, nextNode)
147+
}
143148
} else {
144-
node.static ??= []
145-
nextNode = {}
146-
node.static.push({
147-
name,
148-
caseSensitive,
149-
node: nextNode
150-
})
149+
const name = value.toLowerCase()
150+
const existingNode = node.staticInsensitive?.get(name)
151+
if (existingNode) {
152+
nextNode = existingNode
153+
} else {
154+
node.staticInsensitive ??= new Map()
155+
nextNode = {}
156+
node.staticInsensitive.set(name, nextNode)
157+
}
151158
}
152159
break
153160
}
@@ -217,21 +224,27 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
217224
}
218225
}
219226

220-
function sortStaticSegments(a: NonNullable<SegmentNode['static']>[number], b: NonNullable<SegmentNode['static']>[number]) {
221-
if (a.caseSensitive && !b.caseSensitive) return -1
222-
if (!a.caseSensitive && b.caseSensitive) return 1
223-
return b.name.length - a.name.length
227+
function sortDynamic(a: { prefix?: string, suffix?: string }, b: { prefix?: string, suffix?: string }) {
228+
const aScore =
229+
// bonus for having both prefix and suffix
230+
(a.prefix && a.suffix ? 500 : 0)
231+
// prefix counts double
232+
+ (a.prefix ? a.prefix.length * 2 : 0)
233+
// suffix counts single
234+
+ (a.suffix ? a.suffix.length : 0)
235+
const bScore =
236+
// bonus for having both prefix and suffix
237+
(b.prefix && b.suffix ? 500 : 0)
238+
// prefix counts double
239+
+ (b.prefix ? b.prefix.length * 2 : 0)
240+
// suffix counts single
241+
+ (b.suffix ? b.suffix.length : 0)
242+
return bScore - aScore
224243
}
225244

226245
function sortTreeNodes(node: SegmentNode) {
227-
if (node.static?.length) {
228-
node.static.sort(sortStaticSegments)
229-
for (const child of node.static) {
230-
sortTreeNodes(child.node)
231-
}
232-
}
233246
if (node.dynamic?.length) {
234-
node.dynamic.sort((a, b) => a.name.localeCompare(b.name)) // TODO
247+
node.dynamic.sort(sortDynamic)
235248
for (const child of node.dynamic) {
236249
sortTreeNodes(child.node)
237250
}
@@ -247,12 +260,10 @@ function sortTreeNodes(node: SegmentNode) {
247260

248261
type SegmentNode = {
249262
// Static segments (highest priority)
250-
// TODO: maybe we could split this into two maps: caseSensitive and caseInsensitive for faster lookup
251-
static?: Array<{
252-
name: string
253-
caseSensitive: boolean
254-
node: SegmentNode
255-
}>
263+
static?: Map<string, SegmentNode>
264+
265+
// Case insensitive static segments (second highest priority)
266+
staticInsensitive?: Map<string, SegmentNode>
256267

257268
// Dynamic segments ($param)
258269
dynamic?: Array<{

0 commit comments

Comments
 (0)