在前面的对vue-ssr
改造为koa
的web
框架,我使用了一个第三方npm库。javascript
包名为 已迁移到koa2-webpack-middleware-zm
koa-webpack-middleware-zm
。vue
这个包是我本身由于ssr的特殊需求github
上并无合适的包。java
因此自行参考了koa-webpack-middleware后写出的包。webpack
而且修复原有包的一些 bug。git
这篇博文我将写如下内容github
koa 中间件的编写。web
把
webpack-dev-middleware
这种express
中间件改造为一个koa
中间件。shell
npm 包安装express
npm i koa express -D
koa和express的基本模板。
koa只能用new的方式建立npm
// koa const Koa = require('koa') // ... use code const KoaApp = new Koa() KoaApp.listen(8000)
express能够用方法调用或new的方式建立
// express const Express = require('express') // ... use code const ExpressApp = Express() ExpressApp.listen(8080)
二者的hello。
koa:
// use code KoaApp.use(function(ctx, next){ ctx.body = 'hello koa' })
express:
// use code ExpressApp.use(function(req, res, next){ res.end('hello exress') })
express 中间件运行逻辑
中间件为一个方法接受 req,res,next 三个参数。
中间能够执行任何方法包括异步方法。
最后必定要经过
res.end
或者next
来通知结束这个中间件方法。若是没有执行
res.end
或者next
访问会一直卡着不动直到超时。而且在这以后的中间件也会无法执行到。
koa 的中间件运行逻辑
中间件为一个方法或者其它,这里就讲方法的,接受
ctx,next
两个参数。方法中能够执行任何同步方法。可使用返回一个
Promise
来作异步。中间件经过方法结束时的返回来判断是否进入下一个中间件。
返回一个
Promise
对象koa会等待异步通知完成。then中能够返回next()来跳转到下一个中间件。相同若是
Promise
没有异步通知也会卡住。
express 异步中间件
ExpressApp.use(function(req, res, next){ setTimeout(function(){ res.end('测试') }, 0) })
express 的异步就是最普通的回调
koa 异步中间件
KoaApp.use(function(ctx, next){ return new Promise(function(resolve, reject) { if (ctx.path === '/'){ ctx.body = 'hello koa' resolve() } else { reject() } }).catch(next) })
koa 的异步经过Promise
来作这里我then
不写表明resolve
不切换到下一个中间件。catch
直接绑定next
,用reject
来通知跳转到下一个中间件。
hello-test.js
module.exports = function(req, res, next){ setTimeout(function(){ if (req.path === '/'){ res.end('测试') }else{ next() } }, 0) }
express 使用
const test = require('./hello-test.js') ExpressApp.use(test)
修改到 koa 使用
const test = require('./hello-test.js') KoaApp.use(function (ctx, next){ const res = ctx.res const req = ctx.req const end = res.end return new Promise(function(resolve, reject) { res.end = function () { end.apply(this, arguments) resolve() } test(res, req, reject) }).catch(next) })
经过修改原有的res.end
运行resolve
通知Promise
结束,
修改next
用reject
替代通知Promise
调用next
。
原有的express
组件是经过回调来通知结束的。不要直接await
或者yield
一个组件。它们又不是返回一个Promise
对象。
const test = require('./hello-test.js') KoaApp.use(function *(next){ const res = this.res const req = this.req // 这种写法会致使后面注册的中间件都失效。 yield test(res, req, next) }) KoaApp.use(async function (ctx, next){ const res = ctx.res const req = ctx.req // 这种写法会致使后面注册的中间件都失效。 await test(res, req, next) })
只有在catch
或者是then
中返回next()
才能跳转到下一个组件。
function koaDevMiddleware(expressDevMiddleware) { return function middleware(ctx, next) { return new Promise((resolve) => { expressDevMiddleware(ctx.req, { end: (content) => { ctx.body = content; resolve(false); }, setHeader: (name, value) => { ctx.set(name, value); }, }, () => { resolve(true); }); }).then((err) => { if (err) { return next(); } return null; }); }; } module.exports = koaDevMiddleware;
这是昨天最新的代码当时没想着用reject
来通知next
后面大概要改为这样。
function koaHotMiddleware(expressHotMiddleware) { return function middleware(ctx, next) { return new Promise((resolve) => { expressHotMiddleware(ctx.req, ctx.res, resolve); }).then(next); }; } module.exports = koaHotMiddleware;
欢迎star,issues,fork, pr
下篇博文写
在
npm
上发布你的包以共享给其余人使用。添加测试用例
添加
travis-ci
自动集成测试.