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/ 找到这个骨架应用。