高性能基数树路由库 flexrouter,能同时和React和koa一起用的路由库
发布于 5 年前 作者 vincent178 3116 次浏览 来自 分享

先放链接: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, 但是它实现有点问题,这也是我想自己实现一个版本的原因。

4 回复

很赞 👍

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是没问题的,一旦需要回退就找不到了。 不知道我有没有说清楚。

回到顶部