新一代node.js web开发框架Koa入门学习笔记
原创目录
Koa
新一代 node.js web 开发框架。
构建一台服务器
node 初始化 package.json
npm init -y
参数:
-y 使用所有选项的默认设置,不要一步步确认。
{
"name": "RyeKoa",
"version": "1.0.0",
"description": "Koa 零基本入门学习笔记",
"main": "app.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "觀·自在",
"license": "ISC"
}
安装 Koa 模块
cnpm install koa --save 简写 npm i koa -S
参数:
--save 将在 package.json 将安装包的版本信息添加到
// package.json
{
"name": "RyeKoa",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.13.1"
}
}
创建应用程序条目文件 app.js
最简实现
// app.js
const Koa = require(koa)
const app = new Koa()
app.use(async (ctx, next) => {
ctx.response.body = Hello Koa!
})
app.listen(3000)
这是实现的最简单版本。
Koa 应用程序是一个集合 中间件 函数的对象,以类似堆栈的方式组织和执行。
app.use() 函数用于对中间件进行注册。
ctx 是 Koa 上下文
next 是中间件必须的,调用 next() 用于执行下一个中间件,这里不使用它,因为 ctx.response.body 默认呼叫 next()
上述代码中使用的中间件也可以缩写为以下形式:
app.use(async ctx => {
// 这是 Response 别名
ctx.body = Hello Koa!
})
上下文
Koa Context 将 node 的 request 和 response 对象被封装到单个对象中以供写入。 Web 应用程序和 API 提供了许多有用的方法。 这些操作在 HTTP 在服务器开发中经常使用它们,它们被添加到这一级别,而不是更高级别的框架,这迫使中间件重新实现这一通用功能。
每个 请求将创建一个 Context并作为中间件中的接收方引用,或者。 ctx 标识符,如以下代码片断所示:
app.use(async ctx => {
ctx; // 这是 Context
ctx.request; // 这是 koa Request
ctx.response; // 这是 koa Response
});
为方便起见,许多上下文的访问器和方法被直接委托给它们。 ctx.request 或 ctx.response 除此之外,它们都是一样的。 例如 ctx.body 、 ctx.type 和 ctx.length 委托给 response 对象,ctx.path 和 ctx.method 委托给 request。
Request 别名
以下访问器和 Request 别名等效项:
- ctx.header
- ctx.headers
- ctx.method
- ctx.method=
- ctx.url
- ctx.url=
- ctx.originalUrl
- ctx.origin
- ctx.href
- ctx.path
- ctx.path=
- ctx.query
- ctx.query=
- ctx.querystring
- ctx.querystring=
- ctx.host
- ctx.hostname
- ctx.fresh
- ctx.stale
- ctx.socket
- ctx.protocol
- ctx.secure
- ctx.ip
- ctx.ips
- ctx.subdomains
- ctx.is()
- ctx.accepts()
- ctx.acceptsEncodings()
- ctx.acceptsCharsets()
- ctx.acceptsLanguages()
- ctx.get()
Response 别名
以下访问器和 Response 别名等效项:
- ctx.body
- ctx.body=
- ctx.status
- ctx.status=
- ctx.message
- ctx.message=
- ctx.length=
- ctx.length
- ctx.type=
- ctx.type
- ctx.headerSent
- ctx.redirect()
- ctx.attachment()
- ctx.set()
- ctx.append()
- ctx.remove()
- ctx.lastModified=
- ctx.etag=
启动服务器
node app
因此,使用 node 命令启动服务器并访问本地地址端口。 3000
浏览器访问地址:
http://127.0.0.1:3000/
或 http://localhost:3000/
此时,浏览器会响应:

自动服务器重新部署
Node.js 发展援助 nodemon
修改代码后,每次都需要停机重启。 Koa 应用程序时,所做的更改将生效。
使用了 nodemon 之后,它将监视项目中的所有文件,并在发现任何更改后自动重新启动应用程序。
安装 nodemon
npm i nodemon -g
参数
i 即 install
-g 全局安装(我们都执行通用命令行使用的工具的全局安装)
启动应用程序:
nodemon app
这样,当您修改代码时:
...
app.listen(3000, () => {
console.log("服务器已启动,http://localhost:3000");
})
...
在控制台中,您将看到。 nodemon 自动为您重新启动服务器:
$ nodemon app
[nodemon] 2.0.7
[nodemon] to restart at any time, enter rs
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting node app.js
[nodemon] restarting due to changes...
[nodemon] starting node app.js
服务器已启动,http://localhost:3000
中间件
Koa 应用程序是一个集合 中间件 函数的对象,以类似堆栈的方式组织和执行。
使用 app.use() 函数用于对中间件进行注册。
ctx 是上下文
next 是中间件必须的,调用 next() 用来执行下一个中间件,如果没有,程序就会挂在这里。
const Koa = require(koa)
const app = new Koa()
app.use(async (ctx, next) => {
ctx.name = Koa
next()
})
app.use(async ctx => {
ctx.body = Hello, ${ctx.name}!
})
app.listen(3000, () => {
console.log("服务器已启动,http://localhost:3000");
})
洋葱模型
Koa 新一代 node.js web 开发框架。它最大的特点是其独特的中间件流程控制,这是一个典型的洋葱模型。
下面两个图清楚地显示了中间件最终如何生成请求。在这种模式下,中间件的开发和使用非常方便。


const Koa = require(koa)
const app = new Koa()
app.use(async (ctx, next) => {
console.log(中间件1:开始);
ctx.name = Koa
await next()
console.log(中间件1:结束);
})
app.use(async ctx => {
console.log(中间件2:开始);
ctx.body = Hello, ${ctx.name}!
console.log(中间件2:结束);
})
app.listen(3000, () => {
console.log("服务器已启动,http://localhost:3000");
})
控制台输出:

怎么了,有没有一点感觉。当程序运行时 await next() 当当前程序挂起时,它将进入下一个中间件,并且不会回去继续处理,直到它完成。
Koa 中间件的实现重点
- 上下文 ctx 保存和交付
- 中间件的顺序管理
- next 的使用( 注意 next() 前边的 await )
定制中间件
定制一个中间件一点也不难。
步骤1:定义方法
function MidTest(ctx) {
global.console.log(执行了定制中间件...)
}
第二部分:导出此方法
- 公开函数
- 此函数返回一个参数 ctx 与 next 的 回调函数 。
-
执行我们希望在回调函数中完成的方法。
module.exports = function () { return async function (ctx, next) { MidTest(ctx); // todo await next(); //运行后,将其移交给下一个中间件。 // todo } }
完整的中间件定义:
// ./middleware/mid-test.js
function MidTest(ctx) {
global.console.log(执行了定制中间件...)
}
module.exports = function () {
return async function (ctx, next) {
MidTest(ctx);
await next(); //运行后,将其移交给下一个中间件。
}
}
使用定制中间件:
第一步:引入中间件
const
MidTest = require(./middleware/mid-test)
第二部分:注册中间件
app.use(MidTest())
运行应用程序,将看到定制中间件的执行结果:

Koa 路由
安装路由中间件 koa-router
cnpm i koa-router -S
使用 koa-router
导入路由模块:
const Router = require(koa-router)
实例化的路由(支持传递参数):
const router = new Router()
配置路由:
router.get(/, async (ctx, next) => {
ctx.body = Hello, Koa Router!
})
注册路由中间件:
路由实例 router,单独呼叫 router.routes() 和 router.allowedMethods() 得到两个中间件。然后使用 app.use() 注册这两个中间件。
- 调用router.routes()组装匹配的路由并返回合并的中间件。
-
调用router.allowedMethods()获取在发送不符合要求的请求时返回的中间件。
405 Method Not Allowed或501 Not Implementedapp.use(router.routes()) app.use(router.allowedMethods({ // throw: true, // 引发错误,而不是设置响应头状态 // notImplemented: () => 不支持当前请求所需的功能, // methodNotAllowed: () => 不支持的请求方法 }))
完整的示例代码:
// app.js
const
Koa = require(koa),
Router = require(koa-router)
const
app = new Koa(),
router = new Router()
router.get(/, async (ctx, next) => {
ctx.body = Hello, Koa Router!
})
app.use(router.routes())
app.listen(3000, () => {
console.log("服务器已启动,http://localhost:3000");
})
处理请求
koa-router 提供了 .get、.post、.put 和 .del 方法来处理各种请求,但在实践中, 我们大多数人只会接触到 POST 和 GET ,因此下面的描述仅针对这两种请求类型。
get:用于接收GET请求
router.get(/, async (ctx, next) => {
ctx.body = Hello, Koa Router!
})
post:用于接收POST请求
router.post(/signin, async (ctx, next) => {
ctx.body = Hello, POST!
})
all:用于接收GET与POST请求
router.all(/, async (ctx, next) => {
ctx.body = Hello, POST!
})
请求参数
有时,您需要从 URL 获取具体参数主要有两类: params 和 query 。 这两个参数的取值如下:
params 参数:
router.get(/:catalog/:title, async (ctx, next) => {
ctx.body = Hello, GET! 页面参数 catalog:${ctx.params.catalog} title:${ctx.params.title}
})


query 参数
router.get(/user, async (ctx, next) => {
console.log(ctx.query)
ctx.body = Hello, GET! 页面参数 Name:${ctx.query.name} Age:${ctx.query.age}
})


post 参数
路由嵌套
路由前缀
路由分离
使用静态文件
设置静态目录:public并创建一个文件。 hello.html

安装: koa-static 模块
直接访问是不可访问的,这里我们使用中间件。 koa-static 模块
安装 koa-static 模块
npm i koa-static -S
用法:导入、配置、注册
// app.js
...
const KoaStatic = require(koa-static)
app.use(KoaStatic(__dirname + /public))
...
访问静态资源:

模板引擎
安装:koa-views
cnpm i koa-views -S
cnpm i ejs -S
编写模板
在根目录下创建 views 文件夹,位于 views 下创建 tpl_fruit.ejs 档案。代码如下:
Document
<%=title %>
<% fruits.forEach((fruit)=>{%>
-
<%=fruit %>
<%})%>
使用模板:导入、配置、注册
// app.js
...
const
path = require(path),
views = require(koa-views)
// 注册模板引擎
app.use(views(path.join(__dirname, views), {
map: {
ejs: ejs
}
}))
/**
* 配置路由
* 使用模板引擎输出
*/
router.get(/favourite, async (ctx, next) => {
await ctx.render(tpl_fruit.ejs, {
title: Hello,我最喜欢的水果:,
fruits: [Apple, Watermelon, Strawberry]
})
})
...
访问:http://localhost:3000/favourite

有趣的模板后缀
// 注册模板引擎
app.use(views(path.join(__dirname, views), {
map: {
love: ejs
}
}))
/**
* 配置路由
* 使用模板引擎输出
*/
router.get(/favourite, async (ctx, next) => {
await ctx.render(tpl_fruit.love, {
title: Hello,我最喜欢的水果:,
fruits: [Apple, Watermelon, Strawberry]
})
})
这样,当您自定义模板时,您就可以使用它。 .love 带有后缀的文件:

我们还可以同时使用多个模板引擎:
// 注册模板引擎
app.use(views(path.join(__dirname, views), {
map: {
love: ejs,
html: underscore
}
}))
如果我们只使用一个模板引擎(通常只有一个),那么当我们注册模板引擎时,我们可以用不同的方式编写它:
// 注册模板引擎
app.use(views(path.join(__dirname, views), {
extension: ejs
}))
这样做的好处是,当我们重新配置路由时,我们不需要指定模板的后缀:
/**
* 配置路由
* 使用模板引擎输出
*/
router.get(/favourite, async (ctx, next) => {
await ctx.render(tpl_fruit, {
title: Hello,我最喜欢的水果:,
fruits: [Apple, Watermelon, Strawberry]
})
})
深入 koa-views
上面的代码被传递 app.use(views(path, args)) 注册视图中间件,它返回一个参数。 ctx 与 next 的 回调函数 。
小白的理解:中间件是一个有特殊约定的功能,它有上下文。 ctx 和 next 参数。
// 中间件
`async (ctx, next) => {
ctx.name = Koa
next()
}`
我们可以直接进入 app.use() 直接在以下位置注册中间件:
// 注册中间件
app.use(async (ctx, next) => {
ctx.name = Koa
next()
})
或者定义一个返回中间件的值的函数,然后注册该函数。
app.use(views(path, args))
这是可以理解的 views(path, args) ,我们将继续关注:
该 回调函数 添加到上下文对象 ctx 添加名为 render 用于呈现视图的函数。
以下为 koa-views 源码:
function viewsMiddleware (path, {
engineSource = consolidate,
extension = html,
options = {},
map
} = {}) {
return function views (ctx, next) {
if (ctx.render) return next()
ctx.render = function (relPath, locals = {}) {
return getPaths(path, relPath, extension)
.then((paths) => {
// do something ...
})
}
return next()
}
}
在源代码中,请注意: ctx.render = function (relPath, locals = {}) {} ,这句话是针对上下文的。ctx添加了render方法,这样我们就可以进入。 router.get() 中使用 ctx.render(tpl, {title: 使用模板引擎}) 呈现了页面。
模板引擎 koa-art-template
art-template 中文文档
代码示例:
// package.json
{
"name": "RyeKoa",
"version": "1.0.0",
"description": "学习资源",
"main": "app.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "Rye",
"license": "ISC",
"dependencies": {
"art-template": "^4.13.2",
"koa": "^2.13.1",
"koa-art-template": "^1.1.1",
"koa-router": "^10.0.0",
"koa-static": "^5.0.0",
"koa-views": "^7.0.1"
}
}
// app.js
const
Koa = require(koa),
Router = require(koa-router),
KoaStatic = require(koa-static),
views = require(koa-views),
path = require(path),
render = require(koa-art-template)
const
app = new Koa(),
router = new Router()
/**
* 对静态资源的访问从根开始, 而不是 public
* 例如:http://localhost:3000/hello.html
*/
app.use(KoaStatic(path.join(__dirname, public)))
/**
* 配置模板引擎
* 在 Koa 实例 app 上注册
* 以及对于上下文 ctx 添加 render 方法
*/
render(app, {
root: path.join(__dirname, views),
extname: .html
})
// 配置路由
router.get(/, async ctx => {
ctx.render(user, {
name: dy,
age: 2
})
})
// 合并配置的路由并注册路由中间件,以及允许的请求方法。
app.use(router.routes()).use(router.allowedMethods({
// throw: true, // 引发错误,而不是设置响应头状态
// notImplemented: () => 不支持当前请求所需的功能,
// methodNotAllowed: () => 不支持的请求方法
}))
app.listen(3000, () => {
console.log(服务器已启动,http://localhost:3000);
})
用户信息
用户信息页面
姓名:{{name}}
年龄:{{age}}
做好“模板继承”和“子模板”
我们通常有一个母版页要求,将是通用的。 js、css 和固定的 head、footer 这样的部分被放入母版页,母版页由具有上述共同特征的其他页面继承,便于统一管理和修改。
Bootstrap 它是世界上最受欢迎的前端框架之一,可以轻松快速地构建响应迅速的移动优先网站。
我们的示例目录如下:

在静态资源文件夹中 public 进入我们需要介绍的内容。 bootstrap 资源文件,该文件要求您安装和 配置 koa-static 模块 。
{{block title}}学习资源{{/block}}-三好生
{{block head}}{{/block}}
{{block header}}{{/block}}
{{block content}}页面内容{{/block}}
子模板:
我的博客 | 在线云学习 | AI 学习助手
首页:
{ {extend ./__layout.html}} 继承母版页
{ {include __links.html}} 导入子模板
{ {block title}}{ {title}}{ {/block}} 放入自定义内容
{{extend ./__layout.html}}
{{block title}}{{title}}{{/block}}
{{block head}}
{{/block}}
{{block content}}
{{/block}}
{{block footer}}
{{include __links.html}}
{{/block}}
最终的效果是:

Koa 跨域设置
使用中间件编写跨域设置:
app.use((ctx, next) => {
// 设置允许跨域
ctx.set("Access-Control-Allow-Origin", "*");
ctx.set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
// 请求标头设置
ctx.set(
"Access-Control-Allow-Headers",
Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild,x-token,sessionToken,token
);
if (ctx.method == "OPTIONS") {
ctx.body = 200;
} else {
next();
}
})
配置服务器支持断点续传
配置 Koa 静态资源支持断点延续。 Accept-Ranges 和 Content-Range
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123



