nikic/fast-route 是 PHP 中的快速路由类,通过将多条路由正则表达式合并为一条后进行匹配以提高性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Router {
constructor(routes) {
this.routeMap = []

let offset = 1
const regexRoutes = Object.entries(routes).map(([ route, handler ]) => {
const paramNames = []
const regexRoute = route.replace(/:(\w*)/g, (_, paramName) => {
paramNames.push(paramName)
return '([^/]+)'
})

this.routeMap[offset] = { handler, paramNames }

if (paramNames.length > 0) {
offset += paramNames.length
return regexRoute
}

offset += 1
return `(${regexRoute})`
})

this.regex = new RegExp(`^(?:${regexRoutes.join('|')})$`)
}

dispatch(path) {
const matches = path.match(this.regex)

// 404
if (!matches) return undefined

let offset = matches.findIndex((match, index) => (index > 0) && !!match)
const { handler, paramNames } = this.routeMap[offset]
const routeParams = Object.fromEntries(
paramNames.map(paramName => [paramName, matches[offset++]])
)

handler(routeParams)
}
}

使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const r = new Router({
'/owner': () => console.log('owner'),
'/:owner': params => console.log(params),
'/:owner/:repo': params => console.log(params),
'/:owner/:repo/branches/:branch': params => console.log(params),
})

// => owner
r.dispatch('/owner')

// => { owner: 'facebook' }
r.dispatch('/facebook')

// => { owner: 'facebook', repo: 'react' }
r.dispatch('/facebook/react')

// => { owner: 'facebook', repo: 'react', branch: 'facts' }
r.dispatch('/facebook/react/branches/facts')

// =>
r.dispatch('/facebook/react/branches/facts/page/2')