下一代 Web 框架 Koa

主要内容

  1. 了解 Koa 框架
  2. 学会 koa-genertor
  3. 了解 Node.js Web 框架的演进过程

1.1 Koa 简介

Koa 是 Node.js 的下一代 Web框架。

Koa 是由 Express 原班人马打造,是一个更小更健壮更富有表现力的 Web “微”框架。
进而实现使用 Koa 编写 Web 应用,通过组合各种更高级的异步流程控制中间件,来免除重复繁琐的回调函数嵌套,并极大提升常见错误的处理效率。

关于 Koa 的 V1 和 V2 差异

  1. 要明确的是 v1 和 v2 版本 API 方面基本无差异
  2. Koa v1 是基于 ES6 Generator 的。
  3. Koa v2 正式版本发布前,可通过 koa-convert 支持 3 种中间件写法,更现代,更时尚。
  4. Koa v2 正式版本发布后,主打 async 函数,要求使用 Node.js v7.6 以上版本。
  5. Koa v1 使用隐式的 this 作文上下文,而 Koa v2 则使用显式的 ctx 作为上下文,语义更清晰。

p.s Koa v2 版本在 2017 年 3 月发布

1.1.1 应用场景

以下列出了 Koa 的常用场景。

场景 描述 使用人员
传统 Web 应用开发 Koa 可以开发带有视图渲染和数据库操作的 Web 应用,主要以网站为主,前后端混在一起,开发简单,是入门和快速开发的利器 均可
作为服务端接口 使用 Koa 可以为 pc端,移动端,html5 端等提供 http API 支持 后端开发人员居多
作为独立 API 层 后端程序可能有多种语言实现,业务划分会导致跨域等各种情况出现,此时可以使用 Koa 作为 API 代理,来请求后端 API,处理后再将结果返回给前端 前端开发人员居多
RPC服务组装 由于历史问题,很多应用层采用 RPC 进行服务化,然后组装成 RPC 服务将其包装成最终 HTTP API提供调用。这是非常好的方式,这种场景是 Koa 非常擅长的组装 RPC 服务非常简单,不涉及数据库操作,可以按照前端要求的格式处理 均可
静态 API 模拟 Koa 可以提供静态 API 接口,无须实现具体逻辑,能够加速开发 均可
API 网关 使用 Node.js 实现 HTTP 代理是非常简单的,使用 Koa 能够更好地请求转发 均可
与前端框架集成 Koa为 Vue,React 等前端框架的集成提供开发部署环境的 HTTP 服务,静态 API 服务等,结合使用可以实现服务端渲染或同构开发。 前端开发人员居多
开发 Web 框架 Koa 自身没用绑定任何中间件,使用 Koa 是往往要同时使用多个中间件,所以很多框架更愿意将 Koa 作为内核模块,在其之上进行定制开发。比如,知名框架 ThinkJS 在其 v 3.0 中采用 Koa 作为内核模块,抛弃了之前维护的 HTTP 基础库 均可

1.1.2 开发要点

Koa 自身比较简单,但是要想使用好,需要掌握以下开发要点。

  • Koa 中间件
  • ES6 语法:Koa 是基于 Node.js v4 以上版本进行开发的,所以对 ES6 语法支持的非常好。
  • HTTP 基础
  • 异步流控制:推荐顺序是, async函数 -> Promise -> Generator。
  • 数据库操作:几乎所有的 Web 应用都涉及操作数据库,所以掌握数据库知识非常重要。数据库一般分为关系型数据库和飞关系型数据库。
  • API 接口开发

1.1.3 Koa 入门

Koa v2 的核心是使用面向更新特性的 async 函数的中间件,其正式版本发布前后略有不同。

  • 正式版本发布前:支持 3 种中间件的写法(Promise,Generator,async函数)。
  • 正式版本发布后:推荐使用 ES2017 的 async 函数作为中间件。
下面将会是以代码为主导的示例。
  1. 初始化项目
    这是使用 npm 初始化
// 初始化 Node.js 模块,创建 package.json 配置文件
npm init -y
// 安装 Koa 作为依赖模块
npm  i -S koa@2
// 创建 app.js 作为应用入口
touch app.js  // ( win 版本略有不同,可手动创建 )

接下来在 app.js 中写入以下服务代码:

const Koa = require('koa')
const app = new Koa()

// 日志中间件
app.use( async (ctx, next) => {
  const start = new Date()
  
  console.log('before await..')
  await next()
  console.log('after await...')

  const ms = new Date - start
  console.log(`${ctx.method} ${ctx.url} - ${ms} ms`)
} )

// 响应
app.use( async (ctx, next) => {
  console.log('respones...')
  ctx.body = 'Hello Koa 2'  
} )

app.listen(3000)

下面是对 Koa 代码中的要点进行说明。

  • 中间件使用了 async函数 + 箭头函数,这样的语义比 之前的 ES6 Generator 更加清晰。
  • 参数增加了 ctx,比之前的 ES6 Generator 中间件只能使用隐式的 this 作为上下文更加友好。

在执行 app.js 之前,一定要确保你的 Node.js 是 v7.6 以上的,否则无法直接执行带有 async 函数的代码。

node app.js

tip: 为什么 Koa 中要新增一个 ctx 参数
新增 ctx 参数的最主要的原因是在箭头函数中,this 实在定义时绑定的,而不是在运行时绑定的。

Koa v1 和 Koa v2 的用法差异
Koa v1

const koa = require('koa')
const app = koa();

Koa v2

const Koa = require('koa')
const app = new Koa();

v1 和 v2 的差异主要来源于源码结构的变化

  • v1 部分源码
var app = App.prototype;

module.exports = App;

function App() {
  if (! (this instanceof App) ) {
    return new App;
  }
  this.env = process.env.NODE_ENV || 'development';
  this.subdomainOffset = 2;
  this.middleware = [];
  this.proxy = false;
  this.context = Object.create(context);
  this.request = Object.create(request);
  this.create = Object.create(response);
}
  • v2 部分源码
module.exports = class App extends Emitter {
  constructor() {
    super();
    
    this.subdomainOffset = 2;
    this.middleware = [];
    this.proxy = false;
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.create = Object.create(response);
  }
}

通过上面的源码对比,可以看出 v1 对外导出的函数,而 v2 对外导出的类,需要通过 new 这个关键子来实例化。另外,值得注意的是, v2 源码里,只有 App 进行了类化,其他仍然保持之前的风格。

1.1.4 为什么选择 Koa

为什么要在众多的框架中选择 Koa 呢,理由大概如下。

  • 用 async 函数做异步流程控制时,代码更容易理解。
  • 错误处理的干干净净。无论是 async 函数还是 Promise 规范都能很好地处理异常,另外 Koa 继承自 Event 的,结合 ctx 里的一些 API 能够更简单地处理错误。
  • 具有优雅的回形针中间件机制。通过更少的代码可以完成更多的工作,尤其是能对响应部分做拦截。(可以跟 Express 作对比)
  • 性能非常好。(跟 Express 作对比)
  • Koa 核心代码量比较少,易于定制,易于在其上开发各种 Web框架。
  • 社区生态逐渐完善。
  • 国内外很多公司都已经大量应用 Koa 了,目前 Node.js 的首选 Web 架构是 Koa。
  • 拥有 Egg.js (基于 Koa 的成熟的企业级 Web 开发框架),拥有庞大的插件生态。
  • 拥有 MidwayJS。它基于 Egg.js 生态,使用 TS 编写,提供 IoC 容器,是面向未来的框架。

下面的部分讲继续介绍 Koa-generator 和 Node.js Web 框架的演进之路

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 框架提出的背景 ES6/7带来的变革 自ES6确定和ES7中async/await开始普及,Node的发展变得更加...
    宫若石阅读 8,459评论 1 14
  • 1.简书 koa是由Express原班人马打造,致力于成为一个更小、更富有表现力、更健壮的Web框架。使用koa编...
    不去解释阅读 2,640评论 0 11
  • 中间件是框架额扩展机制,主要用于 HTTP 请求过程。在单一请求响应过程中加入中间件,可以更好地应对负责的业务逻辑...
    yyscc阅读 341评论 0 0
  • 一、背景 Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 ...
    bayi_lzp阅读 10,417评论 6 25
  • 参考资料 https://chenshenhai.github.io/koa2-note/note/static/...
    JunChow520阅读 10,468评论 1 8