先放链接:https://github.com/vincent178/flexrouter
为什么重新发明一个路由轮子?
react-router vue-router express 还有koa 都是用的 path-to-regexp, 将路由转化成正则表达式,然后循环比对当前路径找到符合的路由。在大量路由情况下查找性能会比较差。 Go 有个高性能的http路由 https://github.com/julienschmidt/httprouter, 内部使用 Radix Tree 实现高性能路由查找,我也撸了一个 ts 版本的。
特性
支持前端和后端:
后端例子没有用任何node框架 http 路由 https://github.com/vincent178/flexrouter/tree/master/examples/http-server-with-flexrouter 前端例子是 react 页面路由 https://github.com/vincent178/flexrouter/tree/master/examples/react-router-with-flexrouter
高性能:
在2000+路由的情况下,benchmark数据
path-to-regexp#home x 4,247 ops/sec ±1.82% (83 runs sampled)
flexrouter#home x 4,856,189 ops/sec ±0.71% (88 runs sampled)
path-to-regexp#topic-detail x 4,247 ops/sec ±1.33% (86 runs sampled)
flexrouter#topic-detail x 1,254,182 ops/sec ±0.82% (88 runs sampled)
多种格式支持:
static route: /home
param route: /topic/:id
param route with regex: topic/photo-:id(/\\d+/).jpg
wildcard route: /*site
其他细节 https://github.com/vincent178/flexrouter
fastify也有个类似的实现叫 find-my-way, 但是它实现有点问题,这也是我想自己实现一个版本的原因。
很赞 👍
URL 越长效果越明显,性能大幅度提升
库只是提供了定义路由和查找路由两个接口, 是比较基础的接口。
运用到实际的项目还得再封装一层
以前基于find-my-way写过一个https://github.com/moajs/moa-router
koa
const http = require('http')
const Koa = require('koa');
const app = new Koa();
const router = require('moa-router')()
router.get('/', (ctx, next) => {
ctx.body = {'path': 'root'}
})
router.on('GET', '/test', (ctx, next) => {
ctx.body = {'hello': 'world'}
})
app.use(router.routes());
app.use(async function (ctx, next) {
ctx.body = "default"
});
const server = http.createServer(app.callback())
server.listen(3030, err => {
if (err) throw err
console.log('Server listening on: http://localhost:3000')
})
效果还不错,不知道你说的它的实现有点问题值的是什么
@i5ting 可以看下这个测试用例
test('complex route match', () => {
const router = new Router([
{
path: '/a/b/c', data: 'h1'
},
{
path: '/a/c/d', data: 'h2'
},
{
path: '/a/c/a', data: 'h3'
},
{
path: '/:id/c/e', data: 'h4'
}
]);
expect(router.lookup('/a/b/c').data).toBe('h1');
expect(router.lookup('/a/c/d').data).toBe('h2');
expect(router.lookup('/a/c/a').data).toBe('h3');
expect(router.lookup('/a/c/e').data).toBe('h4');
})
find-my-way 是认为 ‘/a/c/e’ 是不存在的,而实际上它是匹配 ‘/:id/c/e’ 这个路由的。
在实现上,它在找 :
这种路径的时候,是把这种动态node复制给静态的路径 node,在遍历树的时候一旦找不到prefix就用动态的node再尝试一下。这个实现在处理同样深度的node是没问题的,一旦需要回退就找不到了。
不知道我有没有说清楚。
@vincent178 懂了