在很久没有更新的这段时间里,俺做了一个小镇做题家的社交平台。

    本项目受到王路先生 这篇文章 的启发。

    在很久没有更新的这段时间里,俺做了一个小镇做题家的社交平台:https://bbs.mountaye.com

    平台的规则非常猥琐:一小撮做题家互相给其他人出题,做对了的人有加分,做错了倒扣分;挣分数的目的是顺竿往上爬,以便在给讨论区的帖子和评论点赞或者点踩的时候,取得比别人大一点儿的投票权重——闹麻了。

    为了达到这样不可告人的目的,规则背后的计算非常繁琐——什么 先验概率、贝叶斯公式信息熵、二项相对熵……俺全给整上了。

    目前网站堪堪能用,部分功能性能不好,部分功能没做完,但再不冒个泡公众号掉粉要掉完了,但精益求精这种事是没有尽头的,所以先发布了再说。

    在 Cloudflare 上部署 Next.js 全栈项目

    Cloudflare 在壁外被独立开发着誉为“赛博大善人”,因为其提供 serverless 云计算的几乎所有相关服务,而且其中绝大多数都提供免费使用的额度。

    虽然如此,它并不能算是云计算领域的大玩家。这次开发这个项目的过程让我觉得,其中一个原因在于开发难度不小,和平台高度绑定也让一些需求方有所顾虑。很多完整服务器/云虚拟机上正常运行的项目,并不能原样不动地搬运过来;而且具体改造方法不详,散碎隐藏于不怎么完善的文档中。

    当然现在,这种缺点被 AI 给弥补了不少。(本文不构成投资建议。)

    以下记录一些踩过的坑:

    只支持 edge runtime

    标准的 next.js 项目运行在 node.js 上,而 Cloudflare 只支持 edge runtime,虽然也是 next.js 原生支持的,但毕竟很多功能不能用,比如生成静态网站常用的 node.js 的 fs 库。

    在 page router 结构下

    • 所有的 API 路由需要写 export const config = { runtime:”edge” }
    • 所有的页面路由需要写 export const config = { runtime:”experimental-edge” }

    request 和 response 接口不同

    next.js 提供了 NextRequestNextResponse 两个对象,但是 Cloudflare 不支持,在 API 路由中

    • handler(req) 只接受 request 请求这一个参数
    • 依然需要显式返回 return new Response();

    但是 next.js 的 middleware 不受影响,可以用 NextResponse

    next.js 对 Cloudflare 原生数据库的绑定方法

    • D1 是 Cloudflare 家提供的 serverless 关系型数据库产品。
    • workers 是 Cloudflare 家 serverless 计算的产品。
    • pages 原本是 Cloudflare 家静态网站托管的产品,对标 GitHub pages.

    后来 pages 推出了 page function 功能,再后来 page function 乃至整个 pages 和 workers 产品合并了,但是历史原因导致 API 依然有所不同。在 wrangler.toml 同样指定了 D1 的绑定之后

    • worker 的 handler 函数中自带一个 env 参数,然后在函数体内 const d1 = env.D1
    • next.js 项目需要 import { getRequestContext } from "@cloudflare/next-on-pages"; 然后 const d1 = getRequestContext().env.D1

    getServerSideProps 不算服务端

    本来在 client side rendering 中能正常使用的 fetch("/api/***",…),

    • getServerSideProps 中会因为不知道自身的域名而报错,
    • next.js 的 useRouter() 只能在 react components 中使用
    • 又因为不算服务端,所以 wrangler.toml.dev.vars 文件也不能用

    因此 getServerSideProps 的作用很小,除了传递动态路由的变量之外我没找到用途。

    本文收录于以下合集: