Zeit Function 配合 Koa 使用

Zeit 是一家提供网站部署托管服务的公司,他不仅能托管纯静态网站,还提供 Function 功能托管后端服务,例如 Nodejs、Go、PHP... 相比于他提供的服务,由他出品的 React 服务端渲染框架 Next.js 应该使用的更多。如今,Zeit 不仅仅改了名字,同时也修改了服务价格,所有用户都将获得无限的网站流量、无限的构建次数、无限的 Function 调用,对于我这样的白票党来说,什么 Netlify、Firebase 顿时黯然失色。

不久前,我曾使用阿里云的函数计算功能做了个 Google Analytics 的代理,趁此机会,我也来尝试使用下他的 Function 功能。Zeit 的 Function 和阿里云的函数计算(使用 HTTP 触发器)使用起来差不多,传入两个参数,依次为请求对象和响应对象,不用点在于,Zeit 传入的是标准的 Node.js HTTP Request 和 Response 对象,正因为如此,我们可以直接使用 Express、koa 这些框架。

将之前的代码配合 koa 使用:

const Koa = require("koa");
const axios = require("axios");
const uuidv4 = require("uuid").v4;
const koaBody = require("koa-body");

const app = new Koa({ proxy: true });

app.use(
  koaBody({
    multipart: true,
    text: false,
  })
);

app.use(async (ctx) => {
  const requestUUID = ctx.cookies.get("uuid");
  const responseUUID = requestUUID || uuidv4();
  const requestBodyJson = ctx.request.body;

  const gaBody = Object.assign({}, requestBodyJson, {
    v: 1,
    cid: responseUUID,
    uip: ctx.ip || "",
  });

  const gaBodyString = Object.keys(gaBody)
    .map((x) => {
      return `${x}=${encodeURIComponent(gaBody[x] || "")}`;
    })
    .join("&");

  await axios({
    url: "https://www.google-analytics.com/collect",
    method: "post",
    data: gaBodyString,
  });

  if (!requestUUID) {
    ctx.cookies.set("uuid", responseUUID, {
      maxAge: 63072000,
      httpOnly: true,
      sameSite: "none",
      secure: true,
    });
  }

  ctx.status = 204;
});

module.exports = app.callback();

从此,调试函数再也不用使用特定的 CLI 工具或环境,直接 Node.js 跑起。

Zeit 的 Function 文件必须存放在项目 /api 目录下,文件名就是 URL 的访问路径。既然使用了 koa ,那就把所有的请求都交由他处理吧,为此需要在 now.json 中配置 routes:

{
  "version": 2,
  "routes": [{ "src": "/.*", "dest": "/api/index.js" }]
}