Skip to content

Commit 07430f0

Browse files
committed
perf: improve route addition performance by controlling when sorting is performed
1 parent 1e2f4b7 commit 07430f0

2 files changed

Lines changed: 37 additions & 10 deletions

File tree

modules/RouteNode.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ export default class RouteNode {
7373
path: string = '',
7474
childRoutes: Route[] = [],
7575
cb?: Callback,
76-
parent?: RouteNode
76+
parent?: RouteNode,
77+
finalSort?: boolean,
78+
sort?: boolean
7779
) {
7880
this.name = name
7981
this.absolute = /^~/.test(path)
@@ -84,7 +86,11 @@ export default class RouteNode {
8486

8587
this.checkParents()
8688

87-
this.add(childRoutes, cb)
89+
this.add(childRoutes, cb, finalSort ? false : sort !== false)
90+
91+
if (finalSort) {
92+
this.sortDescendants()
93+
}
8894

8995
return this
9096
}
@@ -105,13 +111,17 @@ export default class RouteNode {
105111
this.parser = path ? new Path(path) : null
106112
}
107113

108-
public add(route: Route | Route[], cb?: Callback): this {
114+
public add(
115+
route: Route | Route[],
116+
cb?: Callback,
117+
sort: boolean = true
118+
): this {
109119
if (route === undefined || route === null) {
110120
return
111121
}
112122

113123
if (route instanceof Array) {
114-
route.forEach(r => this.add(r, cb))
124+
route.forEach(r => this.add(r, cb, sort))
115125
return
116126
}
117127

@@ -121,7 +131,7 @@ export default class RouteNode {
121131
)
122132
} else if (route instanceof RouteNode) {
123133
route.setParent(this)
124-
this.addRouteNode(route)
134+
this.addRouteNode(route, sort)
125135
} else {
126136
if (!route.name || !route.path) {
127137
throw new Error(
@@ -134,7 +144,9 @@ export default class RouteNode {
134144
route.path,
135145
route.children,
136146
cb,
137-
this
147+
this,
148+
false,
149+
sort
138150
)
139151
const fullName = routeNode
140152
.getParentSegments([routeNode])
@@ -146,7 +158,7 @@ export default class RouteNode {
146158
name: fullName
147159
})
148160
}
149-
this.addRouteNode(routeNode)
161+
this.addRouteNode(routeNode, sort)
150162
}
151163

152164
return this
@@ -239,7 +251,7 @@ export default class RouteNode {
239251
return buildStateFromMatch(match)
240252
}
241253

242-
private addRouteNode(route: RouteNode, cb?: () => void): this {
254+
private addRouteNode(route: RouteNode, sort: boolean = true): this {
243255
const names = route.name.split('.')
244256

245257
if (names.length === 1) {
@@ -264,9 +276,10 @@ export default class RouteNode {
264276
}
265277

266278
this.children.push(route)
267-
// Push greedy spats to the bottom of the pile
268279

269-
this.sortChildren()
280+
if (sort) {
281+
this.sortChildren()
282+
}
270283
} else {
271284
// Locate parent node
272285
const segments = this.getSegmentsByName(

test/main.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ describe('RouteNode', function() {
5555
i.should.not.equal(0)
5656
})
5757

58+
it.only('should perform a final sort all routes after adding them', () => {
59+
const routes = [...Array(10)].map((_, index) => ({
60+
name: `r${index}`,
61+
path: `/${index}`,
62+
children: [...Array(500)].map((_, childIndex) => ({
63+
name: `r${childIndex}`,
64+
path: `/${childIndex}`
65+
}))
66+
}))
67+
new RouteNode('', '', routes, undefined, null, true)
68+
// No assertion here, if final sort functionality is broken
69+
// the test will exceed the 2s timeout and fail
70+
})
71+
5872
it('should throw an error when trying to instanciate a RouteNode object with plain objects missing `name` or `path` properties', function() {
5973
;(function() {
6074
new RouteNode('', '', [{ name: 'home' }])

0 commit comments

Comments
 (0)