热门看点:Free Arch:将 Koa 服务部署到 Vercel
于是将目光瞄准到 Vercel,Vercel 提供免费的 Serverless Function,虽然类似 AWS Lambda,但又不太一样,所以记录一下。如果只是将 koa 服务部署到 AWS lambda,那么只需要使用一个 serverless-http 的框架转化一下就好。关于薅 AWS Lambda 羊毛的文章已经写过多篇,参见:
一顿操作猛如虎,部署一个万能 BFF
使用 Mocha 和 Chai 测试驱动开发 AWS Lambda API
(资料图)
Koa Js 是由 Express Js 的原班人马设计的 Web 框架,更小巧但是不再捆绑任何中间件,这一点也是我在将它部署到 Vercel 时碰到坑的原因。尽管它比 Express 新,但 Express.js 仍然更加流行,也许这也是 Vercel 内置对 Express.js 的支持的原因吧。
Express Js 目前的星标数在 57.6 K,而 koa 的星标数大约是它的一半多一点:
看了一下 koa 的贡献者列表,我居然也名列其中呢:
Vercel 是一个用来部署前端应用的云平台,但也可以用来构建轻量级的事件驱动 API,并部署到它们的全球边缘网络。
Vercel 的 Serverless Function 有些特别传统 API 托管在运行着的服务器上。当应用需要扩展时,希望更低成本、更灵活、更安全、资源快速分配并启动等等,使用传统服务器很难做到。但是用 Serverless 就比较容易,因为仅仅是一些后端代码片段在无状态环境中运行着,它们由事件(比如 http 请求)触发并只在一次调用中存活。这可以全部自动化并且在毫秒级扩展。更好的是,不用再维护服务器了。开发者只需要关注业务逻辑——返回值的函数。
如果我们部署一个服务器程序到 Serverless Function,我们就为每个请求执行了一个完整的服务器实现,这是一个反模式,因为 Serverless 函数仍然是函数,只应服务于一个目的。将服务器程序部署在 Serverless Function 上,相当于强行将庞大的逻辑混杂在一个函数里。虽然这是一个反模式,但是羊毛在那里,不得不薅。对于有钱的企业级服务器程序,还是建议绕道。
Vercel 的 Serverless Function 和 AWS Lambda 很像,比如都是一个对外暴露 handler 函数的模块,但是特别之处在于其 handler 签名不一样。AWS Lambda 的 handler:
export default const handler = (event, context) => "Hello World"
但是 Vercel 的 handler 接收一个 req 和 res 参数(https://github.com/Jeff-Tian/v/blob/master/api/test.js):
export default function handler(req, res) { const { name = "World" } = req.query; return res.send(`Hello ${name}!`);}
https://v.pa-pa.me/api/test?name=Jeff:
这签名看起来很像是 Express.js 中间件,有意思的是,它真的支持完整的 Express.js 应用,只需要将入口文件放在 /api/index.js 里即可。
Vercel Serverless Function 对 Koa 的支持经过实验,Vercel Serverless Function 是不支持 Koa.js 应用的。因为它的签名和 (ctx, next) => ctx.body = "Hello" 这种 Koa.js 风格就不相容。
koa-to-express想将 Koa 应用搬到 Vercel Serverless Function,但是不希望改已有的 Koa 代码,最自然的方式莫过于增加一个 adapter,将 koa 风格的中间件函数适配成 express.js 的中间件函数。于是找到了 koa-to-express 这个库。
增加 /api/index.js 文件该 index.js 引用 Koa 应用的入口文件,并将它的中间件做个转换,伪装成一个 Express.js 应用。这样,原来的 Koa 应用在服务器环境中仍然照常运行,同时又可以在 Vercel Serverless Function 环境里运行。如果再使用 serverless-http,再在 AWS Lambda 里部署一个适配,那么就是名副其实的“狡兔三窟”了。
其实没有那么顺利,由于原 Koa 应用使用了 koa-router 这个中间件,触发了 koa-to-express 的一个 BUG。于是只能 Fork 了 koa-to-express ,在自己的版本中做了修复。虽然给原作者提交了 PR,但在他合并并发新版之前,我得临时使用自己的版本,于是要对 package.json 做个修改,在安装 koa-to-express 时,从自己的仓库里下载代码:
https://github.com/Jeff-Tian/v/commit/cd11bf4f7100fd61ef9dda98397eb255b764a396#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519
package.json:
- "koa-to-express": "^3.1.4",+ "koa-to-express": "git+https://github.com/jeff-tian/koa-to-express.git",
给它们的 PR 链接:https://github.com/xingxingted/koa-to-express/pull/10/files
完成 /api/index.js最终的 /api/index.js 文件如下:
https://github.com/Jeff-Tian/v/blob/cd11bf4f7100fd61ef9dda98397eb255b764a396/api/index.js
const k2e = require("koa-to-express");process.env.ROUTER_PREFIX = "/api";const app = require("../app");const expressApp = require("express")();app.middleware.map(m => { expressApp.use(k2e(m));})module.exports = expressApp;
重定向Vercel Serverless Function 默认将 /api/xxx 路由到 /api/xxx.js,所以 /api/xy/z,就不会被 /api/index 处理,所以需要增加一个 vercel.json 文件,将所有 /api/ 下的请求,重定向到 index.js:
{ "rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]}
完成效果和在服务器上运行 koa 一模一样:
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...