Koa 简介
Koa
是由 Express
原班团队打造的 Node.js Web
框架,其核心目标是成为更轻量、更具表现力的 Web
应用和 API
开发基础。若您曾因 Express
应用规模扩大后陷入回调地狱而困扰,Koa
通过采用异步函数彻底摆脱回调模式,显著提升错误处理能力。另一项独特特性是级联机制——中间件会先 "向下游" 执行,再逆流 "回溯上游",从而实现更可控的流程管理(本章后续将具体演示)。更多信息请访问 https://koajs.com/ 。
安装和配置 Koa
现在,我们将使用 Backpack
的默认配置(无需创建 Backpack
配置文件)创建一个 Koa
应用,步骤如下:
-
通过
npm
安装Koa
:$ npm i koa
-
使用
/src/
作为Backpack
默认入口目录,并在该目录下创建入口文件,编写极简的Koa
风格代码:// src/index.js const Koa = require('koa') const app = new Koa() app.use(async ctx => { ctx.body = 'Hello World' }) app.listen(3000)
-
以开发模式运行
Koa
应用:$ npm run dev
通过浏览器访问 127.0.0.1:3000
即可看到页面显示 "Hello World"。如果您曾使用 Express
开发 Node.js
应用,会发现 Koa
能以更简洁的代码实现相同功能。接下来,我们将在后续章节中探讨 Koa
的上下文(Context
)机制和级联(Cascading
)工作原理。
什么是 ctx?
您可能已经注意到,我们在上一节编写的极简代码中出现的 ctx
究竟是什么,以及 Express
应用中常见的 req
和 res
对象去了哪里。实际上,在 Koa
中它们并未消失,而是被封装到了一个统一对象中——即 Koa
上下文(Context
),简称 ctx
。我们可以通过以下方式访问请求和响应对象:
app.use(async ctx => {
ctx.request // Node.js 请求对象
ctx.response // Node.js 响应对象
})
由此可见,通过 ctx.request
和 ctx.response
依然能轻松访问这两个核心 HTTP
对象。它们并非被移除,只是被优雅地整合到了 Koa
的上下文对象 ctx
中。接下来,我们将在下一节探讨 Koa
的级联(Cascading
)机制如何运作。
理解 Koa 级联的工作方式
简单来说,Koa
的级联机制通过顺序调用下游中间件,再控制其反向回溯上游来实现。我们通过一个简单的 Koa
应用来演示这一核心特性:
-
在
/src/
目录创建index.js
文件(如前文所示基础结构):// src/index.js const Koa = require('koa') const app = new Koa() app.use(async ctx => { console.log('Hello World') ctx.body = 'Hello World' }) app.listen(3000)
-
在
Hello World
中间件前插入三个中间件:app.use(async (ctx, next) => { console.log('Time started at: ', Date.now()) await next() }) app.use(async (ctx, next) => { console.log('I am the first') await next() console.log('I am the last') }) app.use(async (ctx, next) => { console.log('I am the second') await next() console.log('I am the third') })
-
运行开发模式后终端将输出:
Time started at: 1554647742894 I am the first I am the second Hello World I am the third I am the last
执行流程说明:
请求依次流经 Time started at: → I am the first → I am the second 最终到达 Hello World。当没有更多下游中间件时,会按 I am the third → I am the last 顺序回溯上游。
完整示例可在 |
接下来,我们将介绍开发全栈 Koa
应用需要安装的关键依赖(使其具备 Express
类似功能)。
为 Koa 应用安装依赖
Koa
的设计理念是极简主义,其核心不包含任何中间件。与 Express
自带路由功能不同,Koa
默认不提供路由系统,这要求开发者从第三方包中选择解决方案(可参考 Koa GitHub 主页 https://github.com/koajs )。经过实践测试,部分路由包可能不完全符合需求。本书主要使用 koa-router
进行路由管理,同时结合其他关键依赖构建 Koa API
开发骨架。以下是具体实现步骤:
-
安装
koa-router
路由模块$ npm i koa-router
在入口文件中导入
koa-router
,并添加一个根路由/
,如下所示:// src/index.js const Router = require('koa-router') const router = new Router() router.get('/', (ctx, next) => { ctx.body = 'Hello World' }) app .use(router.routes()) .use(router.allowedMethods())
你可以在
Koa
的GitHub
仓库 https://github.com/koajs/koa-router 找到关于这个中间件的更多信息。这个模块是从ZijianHe/koa-router
(https://github.com/ZijianHe/koa-router)fork
过来的,是Koa
社区中最广泛使用的路由模块。它提供了类似Express
的路由方式,使用app.get
、app.put
、app.post
等。它还支持其他重要特性,例如多路由中间件以及多个和可嵌套的路由器。 -
安装
koa-bodyparser
请求体解析模块$ npm i koa-bodyparser
在入口文件中导入
koa-bodyparser
,注册它,并创建一个/post
根路由,如下所示:// src/index.js const bodyParser = require('koa-bodyparser') app.use(bodyParser()) router.post('/post', (ctx, next) => { ctx.body = ctx.request.body // 获取表单数据 })
你可以在
Koa
的GitHub
仓库 https://github.com/koajs/bodyparser 找到关于这个中间件的更多信息。你可能想知道:什么是body parser
呢?当我们处理HTML
表单时,我们使用application/x-www-form-urlencoded
或multipart/form-data
在客户端和服务器端之间传输数据,例如:// application/x-www-form-urlencoded <form action="/update" method="post"> //... </form> // multipart/form-data <form action="/update" method="post" enctype="multipart/form-data"> //... </form>
HTML 表单的默认类型是 application/x-www-urlencoded。如果我们想读取 HTTP POST、PATCH 和 PUT 请求的数据,我们需要使用 body parser。body parser 是一种中间件,它可以解析传入的请求,将包含表单数据的块组装起来,然后创建一个包含表单数据的 body 对象,这样我们就可以通过 ctx 对象的 request 属性来访问这些数据,如下所示:
ctx.body = ctx.request.body
-
安装
koa-favicon
网站图标模块$ npm i koa-favicon
在入口文件中导入
koa-favicon
,并使用favicon
的路径注册它,如下所示:// src/index.js const favicon = require('koa-favicon') app.use(favicon('public/favicon.ico')) // 需提前创建 favicon.ico 文件
你可以在
Koa
的GitHub
仓库 https://github.com/koajs/favicon 找到关于这个中间件的更多信息。它是一个用于提供网站图标(favicon
)的中间件。所以,让我们创建一个favicon.ico
文件,并将其保存在项目根目录下的/public
文件夹中。当你刷新首页时,你应该能在浏览器的标签页上看到这个网站图标。 -
安装
koa-static
静态资源模块$ npm i koa-static
在入口文件中导入
koa-static
,并使用以下路径注册它,如下所示:const serve = require('koa-static') app.use(serve('.')) // 开放根目录访问 app.use(serve('static/fixtures')) // 开放/static目录访问
你可以在 Koa
的 GitHub
仓库 https://github.com/koajs/static 找到关于这个中间件的更多信息。Koa
默认情况下不允许你提供静态文件。因此,这个中间件将允许你从你的 API
提供静态文件。例如,我们刚才设置的路径将允许我们从项目根目录下的 /static
文件夹访问以下文件:
-
GET /package.json 位于 127.0.0.1:3000/package.json
-
GET /hello.txt 位于 127.0.0.1:3000/hello.txt
在接下来的章节中,当我们使用 Koa
创建 API
时,我们将使用这个骨架。现在,让我们在下一节中了解如何将 Koa
与 Nuxt
集成。
你可以在我们的 GitHub
仓库的 /chapter-8/koa/skeleton/
找到这个骨架应用。