提到 Node.js 開發,不得不提目前煊赫一時的兩大框架 Express 和 Koa。 web
Express 誕生已有時日, 是一個基於 Node.js 平臺的極簡、靈活的 web 應用開發框架,主要基於 Connect 中間件,而且自身封裝了路由、視圖處理等功能,使用人數衆多。 express
Koa 相對更爲年輕, 是 Express 原班人馬基於 ES7 新特性從新開發的框架,框架自身不包含任何中間件,不少功能須要藉助第三方中間件解決,可是因爲其基於 ES7 async 特性的異步流程控制,解決了 "callback hell" 和麻煩的錯誤處理問題,大受開發者歡迎。Koa 目前已經升級到了 2.x,如下代碼示例都會使用 Koa 2.x。app
二者建立一個基礎的 Web 服務都很是簡單,寫法也基本相同,最大的區別是路由處理 Express 是自身集成的,而 Koa 須要引入中間件。框架
// Express const express = require('express') const app = express() app.get('/', function (req, res) { res.send('Hello Express') }) app.listen(3000)
// Koa const Koa = require('koa') const route = require('koa-route') const app = new Koa() app.use(route.get('/', async (ctx) => { ctx.body = 'Hello Koa' })) app.listen(3000)
Express 自身集成了視圖功能,提供了 consolidate.js 功能,支持幾乎全部 JavaScript 模板引擎,並提供了視圖設置的便利方法。
Koa 須要引入 koa-views 中間件。koa
// Express const express = require('express') const app = express() app.set('views', __dirname + '/views') app.set('view engine', 'pug') app.get('/', function (req, res) { res.render('index', { title: 'Express' }) })
// Koa const Koa = require('koa') const route = require('koa-route') const views = require('koa-views') const app = new Koa() app.use(views(path.join(__dirname, './views'), { extension: 'pug' })) app.use(route.get('/', async (ctx) => { await ctx.render('index', { title: 'Koa' }) }))
Koa 的中間件採用了洋蔥圈模型,全部的請求在通過中間件的時候都會執行兩次,可以很是方便的執行一些後置處理邏輯。
例如,咱們常常須要計算一個請求的響應時間,在 Koa 中, 咱們能夠在中間件的開始記錄初始時間,當響應返回時,代碼執行又回到了原來的中間件,此時根據當前時間和初始時間的時間差便獲得了響應時間。異步
function responseTime() { return async function responseTime(ctx, next) { const start = Date.now() await next() // wait for other middleware to run const delta = Math.ceil(Date.now() - start) ctx.set('X-Response-Time', delta + 'ms') }) }}
而在 Express 中,響應返回時代碼執行並不會回到原來的中間件,此時咱們須要經過監聽 response.writeHead
得到響應返回的時機:socket
const onHeaders = require('on-headers') function responseTime () { return function responseTime (req, res, next) { const startAt = process.hrtime() onHeaders(res, function onHeaders () { const diff = process.hrtime(startAt) const time = diff[0] * 1e3 + diff[1] * 1e-6 res.setHeader('X-Response-Time', time + 'ms') }) next() } }
Express 使用 Node 約定的 "error-first 回調" 處理異常,並經過中間件傳播。
Koa 經過同步方式編寫異步代碼,能夠經過 try catch
處理異常,很是天然。async
// Express app.use(function (err, req, res, next) { res.status(err.status || 500).send('error') })
// Koa app.use(async (ctx, next) => { try { await next() } catch (err) { ctx.app.emit('error', err) ctx.status = err.status || 500 ctx.body = { message: err.message } } })
Koa 新增了一個 Context 對象,用來代替 Express 中的 Request 和 Response,做爲請求的上下文對象。
Context 上除了 Request 和 Response 兩個對象以外,還有 Node.js 原生提供的 req 、res、socket 等對象。ui