koa 框架一直都保持着简洁性, 它只对 node 的 HTTP 模块进行了封装, 而在真正实际使用, 我们还需要更多地像路由这样的模块来构建我们的应用, 而 koa-router 是常用的 koa 的路由库. 这里通过解析 koa-router 的源码来达到深入学习的目的.
源码架构图

调用链路-routes()

HTTP请求调用流程

Usage
const Koa = require('koa');
const Router = require('koa-router');const app = new Koa();
const router = new Router();
router.get('/', async (ctx, next) => {
console.log('index');
ctx.body = 'index';
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);
Router
function Router(opts) {
if (!(this instanceof Router)) {
return new Router(opts);
} this.opts = opts || {};
this.methods = this.opts.methods || [
'HEAD',
'OPTIONS',
'GET',
'PUT',
'PATCH',
'POST',
'DELETE'
];
// 存放router.param方法指定的参数的中间件
this.params = {};
// 存放layer实例
this.stack = [];
};
Layer
function Layer(path, methods, middleware, opts) {
this.opts = opts || {};
this.name = this.opts.name || null;
this.methods = [];
// 存放path路径参数的一些属性,eg: /test/:str => { name: str, prefix: '/' ....}
this.paramNames = [];
// 存放该路由的中间件
this.stack = Array.isArray(middleware) ? middleware : [middleware]; methods.forEach(function(method) {
var l = this.methods.push(method.toUpperCase());
// 如果支持get请求,一并支持head请求
if (this.methods[l-1] === 'GET') {
this.methods.unshift('HEAD');
}
}, this);
// ensure middleware is a function
this.stack.forEach(function(fn) {
var type = (typeof fn);
if (type !== 'function') {
throw new Error(
methods.toString() + " `" + (this.opts.name || path) +"`: `middleware` "
+ "must be a function, not `" + type + "`"
);
}
}, this);
this.path = path;
// 将路由转为正则表达式
this.regexp = pathToRegExp(path, this.paramNames, this.opts);
debug('defined route %s %s', this.methods, this.opts.prefix + this.path);
};
给Router实例挂载HTTP方法
/**
* Create `router.verb()` methods, where *verb* is one of the HTTP verbs such
* as `router.get()` or `router.post()`.









