koa

前面章節已經介紹了源自於 Koa 的中間件和路由設計,前面介紹的靜態資源服務器和路由能夠經過 koa 的中間件輕鬆實現,後面章節要介紹的企業級 web 框架 egg.js 正是基於 koa 開發的,在本章的最後簡單介紹一下 koa 的使用前端

koa 是什麼

next generation web framework for node.jsnode

Koa 是一個使用 Node.js 的 web 開發框架,其核心是前面章節中反覆使用的洋蔥模型中間件,經過中間件解決 web 開發中的 http 處理、業務邏輯實現,web 框架須要具有兩個最基本的特徵git

  1. 提供 web 開發常見的各類基礎功能
  2. 提供一套規範的編碼方式,讓開發者能夠聚焦在業務邏輯實現,代碼就能夠在框架內按照預期執行

有個說法講庫和框架的區別:You call library, framework calls you.github

koa 的 web 處理基礎功能經過中間件提供,其開發規範也是創建在洋蔥模型中間件基礎上,如今使用的是 koa 2.x 版本,在此以前 Node.js 社區 web 框架通過了幾個里程碑web

Express

Express 是 Node.js 的第一代流行 web 開發框架,主要是對 http 模塊進行封裝,並提供了路由、模板渲染等 web 開發經常使用功能,功能齊全但須要全量引用express

因爲出現早於 Promise,錯誤處理使用 Node.js 的 callback 風格,相應有了回調地獄問題,不過隨着 Promise 流行,如今 Express 4.x、5.x 已經沒了這個問題npm

Express 中間件是線性執行的,每個中間件處理完成以後只有兩個選擇api

  1. 交給下一個中間件
  2. 返回 response

只要是離開中間件後就再也沒法返回,這樣的設計讓邏輯很是簡單,但在不少須要屢次處理請求的實現上變得複雜:好比統計一個請求的耗時,在 Express 中充斥着大量利用事件或者回調來 hack 這種需求的處理方式安全

exports.responseTime = function () {
  return function (req, res, next) {
    req.startTime = new Date(); // 開始時間

    const trackTime = function () {
      const endTime = new Date(); // 結束時間
      const duration = endTime - req.startTime;
      console.log('X-Response-Time: ', duration + 'ms');
    }

    res.once('finish', trackTime);
    res.once('close', trackTime);
    return next();
  }
}
複製代碼

由於其簡單、功能高度集成的特性,Express 如今仍然是最流行的 Node.js web 開發框架,但功能高度集成帶來的不靈活和中間件的線性調用特性讓愈來愈多企業級 web 框架封裝都選擇了使用 koa服務器

koa 1.x

Koa 一樣出自 Express 團隊之手,除了 API 變化,相對於 Express 作了兩個最重要的變動

  1. 再也不內置任何中間件,全部 web 處理中間件都須要引用,靈活性和複雜性相伴而來(從這個角度講 Express 才更像是 web 框架)
  2. 利用 generator 特性實現洋蔥模型中間件,異步處理再也不依賴 callback(主要靠 co 模塊實現)

異步的代碼書寫起來更像是同步代碼了,但使用 generator 中間件編寫風格如今看起來會感受怪怪的

app.use(function *(next) {
  const startTime = new Date();
  yield next;
  const duration = new Date - startTime;
  console.log('X-Response-Time: ', duration + 'ms');
})
複製代碼

koa 2.x

理念和 Koa 1.x 一致,不過推薦異步處理變成了 async/await,其中間件實現也就是前面介紹過的 koa-compose,中間件編寫風格好理解了不少

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});
複製代碼

koa 2.x 也把以前使用 this 獲取請求、響應等對象修改成了使用 ctx 對象

Hello world

使用 koa 編寫 hello world 很是簡單

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

// response
app.use(ctx => {
  ctx.body = 'Hello Koa';
});

app.listen(3000);
複製代碼
  1. app.use(middleware):註冊中間件
  2. app.listen(port):和 http 模塊功能同樣
  3. app.context:全應用共享的環境信息

context

context 對象在每一個請求中被建立,是 koa 對當前請求的 request、response 對象封裝,並提供了不少實用處理工具方法,作爲中間件的第一個參數被傳入

app.use(async (ctx, next) => {
  ctx; // is the Context
  ctx.request; // is a koa Request
  ctx.response; // is a koa Response
});
複製代碼

context 中用幾個經常使用的屬性

  1. ctx.request: koa 封裝的 request 對象,中間件應該儘可能使用
  2. ctx.req:Node.js 原生的 request 對象
  3. ctx.response:koa 封裝的 response 對象,中間件應該儘可能使用
  4. ctx.res:Node.js 原生的 response 對象
  5. ctx.state:koa 推薦的命名空間,用於經過中間件傳遞信息到前端視圖
  6. ctx.app:對應用實例 app 的引用
  7. ctx.cookies:cookie 操做對象
  8. ctx.throw:經過 http status 拋出錯誤,讓 koa 能夠正確處理
ctx.throw(400);
ctx.throw(400, 'name required');
ctx.throw(400, 'name required', { user: user });
複製代碼

request & response

koa 封裝的 request 和 response 對象包含了 Node.js 原生 req、res 的所有屬性,而且提供了不少快捷操做,再也不一一介紹

  1. request api
  2. response

response.body

經過設置 response.body 能夠設置 http 響應,設置的值能夠是如下類型

  • string
  • Buffer
  • Stream 可讀流
  • Object || Array
  • null 不返回響應

靜態資源服務器

使用 koa-static 中間件能夠輕鬆實現前面章節介紹的靜態資源服務器

const path = require('path');
const Koa = require('koa');
const static = require('koa-static');

const app = new Koa();

const root = path.join(__dirname, './public');
app.use(static(root, {}));

app.listen(3000);
複製代碼

Getting start

官方介紹了三個學習 koa 的網站

  • Kick-Off-Koa - An intro to Koa via a set of self-guided workshops.
  • Workshop - A workshop to learn the basics of Koa, Express' spiritual successor.
  • Introduction Screencast - An introduction to installing and getting started with Koa

其實只要瞭解了 Node.js 的 http 模塊和 koa 的洋蔥模型中間件,koa 很是好理解,但實現一個完整的 web 網站須要整合大量的中間件( koa 核心維護者死馬整理了一些經常使用的 www.npmjs.com/package/koa…

var koa = require('koa');
var middlewares = require('koa-middlewares');
var router = middlewares.router();

var app = koa();

router.get('/', function *(){
  this.body = 'hello koa-middlewares';
});

app.use(middlewares.bodyParser());
app.use(middlewares.conditional());
app.use(middlewares.etag());
app.use(middlewares.compress());
middlewares.csrf(app);
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(7001);
複製代碼

看起來很是恐怖,這也是爲何會有不少基於 koa 的 web 開發框架,針對特定的功能整合了相應的中間件,併爲開發者處理了 web 安全、性能等相關問題,接下來介紹其中的佼佼者——企業級的 web 開發框架 egg.js

相關文章
相關標籤/搜索