
2.2.1 koa-router
Koa中可用的路由非常多,Koa官方就给出了3个,分别是route、trie-router和joi-router。它们都非常简单,可以应用在小型项目中。但对于有Express开发背景的人来说,肯定更希望使用和Express的路由风格类似的路由,这样会更简单。这其实是很多人的共性需求,为了实现这一需求,koa-router这个开源项目便诞生了。
koa-router的特性如下。
○ 属于Express风格的路由,使用app.get、app.put、app.post等,可以通过指定方法来访问请求。
○ 支持HTTP状态码(405方法不允许,501方法未实行)。
○ 支持多个路由中间件。
○ 支持多路由。
○ 支持嵌套路由。
○ 支持async/await写法(koa-router v7.x)。
koa-router的版本说明如下。
○ koa-router v5.x适用于Koa v1。
○ koa-router v7.x适用于Koa v2,并且支持async/await写法。
以前使用koa-router还是比较麻烦的,因为要区分版本,现在大家都直接使用Koa v2了,所以安装最新版本更好。
➘ 从最简单的示例开始
下面以Koa v2版本为例,演示最简单的koa-router用法。

app.js代码如下。

启动服务器时需要在终端键入如下命令。

然后在浏览器中访问刚启动的服务器地址http://127.0.0.1:3002/(如果不能访问,请关闭VPN代理)。
以上代码中的核心解读如下。
(1)使用时需要先进行require操作。注意后面的括号,不要漏写。

(2)进行路由定义。

其中,get是HTTP动词对应的请求方法,'/'是路由路径,function(ctx,next){}是处理该路径的Koa中间件(中间件可以有多个)。核心的操作在Koa中间件中进行。
(3)将路由挂载到app上。挂载方法很简单,一行代码就可以搞定。

➘ 为什么会有路由
第1章讲Node.js Web框架演进的时候说过,多URL处理非常麻烦,因而Connect、Express、Koa这些框架诞生了。一个完整的Web工程需要提供很多服务,在这种情况下,多URL的弊端也是极其明显的。
下面来看一下中间件是如何处理多URL的。
方式1:使用if/else语句处理,代码如下。

方式2:使用多个中间件处理,代码如下。

这两种方式只适合在一个中间件中处理差异。很明显,后一种方式好于前一种。可是每次都要判断ctx.path(如下面的代码所示),大家是不是觉得很麻烦?

为了把这些细节隐藏起来,路由便产生了,它的本质其实就是对ctx.path进行抽象。如果各位读者有兴趣,可以翻阅一下koa-router中的源码。
路由的实现原理简单说明如下。
○ 定义路由。
○ 路由的路径会被转译成正则表达式。
○ 匹配请求,使用中间件进行处理。
koa-router模块的核心是路由解析,使用的是path-to-regexp模块。Express使用这个模块做路由解析,koa-router项目中用的也是这个模块,所以Express和Koa的路由使用风格是一致的。
➘ 对比Express路由
Express里路由的定义如下。

koa-router路由的定义如下。

整体来看,二者风格是相同的,差别在于中间件的写法,所以还是中间件决定了路由的定义方式。path-to-regexp模块是Express和koa-router共用的解析路径的模块,所以它们支持的URL风格也是一样的。以URL命名参数为例看一下具体的路由解析结果。
