要解决的问题
最近采用koa2在公司上架了2个Node.js应用,采用的是前后端分离的SPA模式,koa-router是这个项目的路由模块。 为了让前端的url比较友好,单页面路由采用了path形式而非hashbang的url。 这样的一个要求就是对于每个页面级别的网络请求,都必须返回单页面应用html。 这样的业务场景下,就要求我对url进行分析来进行逻辑分发了。
逻辑分发
我在设计路由分发的时候,根据url采用的是如下三条分发原则。
- /api 开头的表明是ajax请求
- /. 有extension结尾的表明是静态资源
- 除去以上两种情形下的网络请求,来自于单页面应用,都返回index.html
基于第三种场景,我需要写一个正则条件,去除1和2的匹配情况。 而写过复杂正则的同学都知道写一个非匹配的正则其实是蛮纠结的事情。 于是我就去读了一遍koa-router的源码,还是没有找到类似axios库等的interceptor的东西。
因此,我就自己写了个interceptor模块封装了一层koa-router.
上源码
const RouterInterceptor= (koaRouter,interceptor)=> (ctx,next)=>{
return Promise.resolve(interceptor(ctx,next)).then((boolean)=>{
if(boolean===true){
return koaRouter.routes()(ctx,next)
}else{
return next()
}
})
};
module.exports = RouterInterceptor;
如上,koa-router-interceptor是个高阶函数,interceptor是处理正则逻辑的, 只有返回true,才会走koa-router的逻辑,我们看下实际使用的效果。
const app = new Koa();
const KoaRouter = require('koa-router')();
const KoaRouterInterceptor = require('koa-router-interceptor');
KoaRouter.get(/.*/,(ctx,next)=>{
ctx.body="hello world"
})
app.use(KoaRouterInterceptor(KoaRouter,(ctx,next)=>{
// 只有这个返回true,才会走koa-router配置的逻辑分发
return !(ctx.path.substr(0,4)=='/api' || /\./.test(ctx.path));
}));
本来我需要在router.get()里面写的正则匹配,现在变成了一个动态化的函数处理, 对于项目的可维护性和动态性就大大的增强了。
代码使用
代码是纯Promise的代码风格,兼容koa1 和 koa2,有需求的同学可以看看
npm install koa-router-interceptor
好久没来cnode社区逛了,逛了一圈发现了不少可以学习的好文章。 今后要多来
哦, 看这个 https://github.com/magicdawn/impress-router
const app = new (require('koa'))
const router = new (require('impress-router'))
app.use(router)
router.use('/api', api)
router.use('/public', _static()) // koa-static
router.use((ctx) => ctx.body = html)
@magicdawn 我觉得没必要重写一个额。。不过看了下实现,貌似和koa-router挺像