在 Cloudflare Worker 中通过 Supabase JS 查询 Supabase 数据
Supabase 提供的是基于 Postgres 的完整后端平台,而 Cloudflare Workers 是运行在全球边缘节点的无服务器运行时。这篇实战指南以仓库中的 examples/with-cloudflare-workers 示例为蓝本,完整演示了如何在 Cloudflare Worker 中安装并初始化 @supabase/supabase-js 客户端,把项目 URL 与发布密钥通过 wrangler secret 安全注入 Worker,然后执行 articles 表查询并以 application/json 响应返回给浏览器。读完本文,你将掌握一套可复制、可运行的“边缘端直连 Supabase”的最小实现,并能看懂仓库中完整可运行的 src/index.js 源码。
场景概述:为什么要在边缘端查询 Supabase
Supabase JS(即 @supabase/supabase-js)是一个 NPM 包,它为 JavaScript / TypeScript 应用访问 Supabase 项目提供了简单统一的接口。它支持三种典型能力:
- 查询与变更数据:通过对象关系映射(ORM)风格语法读写 Postgres 表中的数据;
- 实时订阅:监听数据库变更并推送实时事件(本文不展开);
- 服务端或客户端运行:既可在浏览器中运行,也可运行在 Node.js、Deno、Bun 以及 Cloudflare Workers 等运行时。
Cloudflare Worker 与 Supabase 的组合价值在于:Worker 在离用户最近的边缘节点执行,开发者可以在请求到达源站之前完成轻量数据聚合、权限校验或响应加速。本文对应的示例正是把“读取文章列表并返回 JSON”这一任务整体下沉到 Worker 完成。
在仓库中,examples/with-cloudflare-workers 是一个自包含的最小示例目录,完整结构如下:
examples/with-cloudflare-workers/
├── src/
│ └── index.js # Worker 入口:创建 Supabase 客户端并查询数据
├── package.json # 依赖与脚本(wrangler、@supabase/supabase-js)
├── wrangler.toml # Cloudflare Worker 配置
└── README.md # 教程说明
准备工作:获取项目 URL 与访问密钥
在使用 Supabase JS 之前,需要两个来自 Supabase 项目的信息:
- 项目 URL:形如
https://<project-ref>.supabase.co的 RESTful 端点地址; - 访问密钥:用于通过网关鉴权。该密钥可在 Supabase Dashboard 的
Settings > API中获取。
原文教程里该密钥被称作 Anon Key。需要说明的是,随着生态对密钥语义的澄清,当前仓库内多个示例已将代码与文档中的命名统一为 publishable key(可发布密钥),例如 src/index.js 中的环境变量名是 SUPABASE_PUBLISHABLE_KEY,nextjs-full 示例也使用 NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY。本质上它就是 createClient 的第二个参数,用于网关层鉴权。
这类密钥在客户端环境暴露是预期行为,因此使用时应配合数据库行级安全策略(RLS)约束可读数据范围,不要把 service_role 这类高权限密钥放进边缘 Worker。
第一步:安装 Supabase JS
在 Worker 项目目录内,用 npm 安装官方客户端:
npm i @supabase/supabase-js
仓库中的 package.json 给出了完整依赖声明,与本示例一致:
{
"name": "supabase-at-the-edge",
"devDependencies": {
"wrangler": "2.20.1"
},
"dependencies": {
"@supabase/supabase-js": "^2"
},
"scripts": {
"start": "wrangler dev",
"deploy": "wrangler publish"
}
}
可以看到,示例同时声明了两个运行时层面的依赖:应用依赖 @supabase/supabase-js 的 v2 大版本;开发依赖 wrangler CLI(此示例锁定在 2.20.1),用于本地开发、密钥管理与发布。npm scripts 中预置了 start(等价于 wrangler dev)与 deploy(等价于 wrangler publish)两条常用命令。
第二步:编写 Worker 入口并查询数据
示例的核心逻辑集中在 src/index.js,全文不足 20 行,逐段拆解如下。
首先导入客户端工厂函数,并导出一个默认对象。Cloudflare Worker 的模块化语法约定:默认导出的对象需要暴露一个 fetch 方法,作为请求的入口处理器:
import { createClient } from '@supabase/supabase-js'
export default {
async fetch(request, { SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY }) {
const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY)
const { data } = await supabase.from('articles').select('*')
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
},
})
},
}
这里蕴含三个关键知识点:
-
环境变量的注入方式:
fetch的第二个参数是env绑定对象,其中包含 Worker 可访问的全部环境变量与绑定资源。示例通过解构语法直接取出SUPABASE_URL与SUPABASE_PUBLISHABLE_KEY,它们由 Cloudflare 侧以密钥(secret)形式注入,详见下文“密钥管理”一节。 -
客户端初始化:
createClient(projectUrl, anonKey)是 Supabase JS 的标准初始化签名。第一个参数是项目 REST 端点,第二个参数是密钥。初始化完成后即可使用 ORM 风格的查询语法:const { data } = await supabase.from('articles').select('*')该调用等价于从 Postgres 的
articles表读取全量记录,返回结果按解构约定放入data字段。仓库中其它示例(如 expo-social-auth 的客户端封装)采用完全相同的createClient初始化模式,验证了这套 API 是跨端一致的。 -
返回 JSON 响应:
supabase-js返回的是 JavaScript 对象,而网络响应体要求字符串或字节流。因此需要先用JSON.stringify(data)序列化,随后在Response中设置Content-Type: application/json请求头,通知浏览器按 JSON 解析响应内容。这是 Worker 返回结构化数据时的标准做法。
第三步:配置 wrangler.toml
仓库中的 wrangler.toml 内容如下:
name = "supabase-at-the-edge"
main = "src/index.js"
compatibility_date = "2022-07-26"
三个字段的含义分别是:
name:Worker 在 Cloudflare 上的部署名称;main:入口模块文件,即上文中的src/index.js;compatibility_date:指定 Workers 运行时的兼容性日期,锁定某版本的运行时行为,避免将来行为变更破坏现有代码。
第四步:本地开发运行
编辑完成后,先通过 wrangler 的本地开发服务器验证代码行为:
npx wrangler dev
wrangler dev 会在本机启动一个模拟 Workers 运行时的开发服务器,绑定 wrangler.toml 中的入口文件。本地调试时需要注意:正式密钥以 Cloudflare 账户级 secret 形式存储,默认不会出现在本地环境。实践中可参考 wrangler 对本地变量的支持,在开发阶段补充可用的本地配置后再行联调。
第五步:用 wrangler secret 注入密钥
正式环境中,项目 URL 与发布密钥不应硬编码进源码,而应作为 secret(密钥) 存储在 Cloudflare 账户中。Wrangler 提供统一命令创建密钥:
npx wrangler secret put NAME
按提示输入密钥值后,该变量会加密保存在 Cloudflare 侧,并在 Worker 运行时注入 env 绑定对象。为当前示例依次创建两个密钥:
添加 SUPABASE_URL 密钥
npx wrangler secret put SUPABASE_URL
添加 SUPABASE_PUBLISHABLE_KEY 密钥
npx wrangler secret put SUPABASE_PUBLISHABLE_KEY
执行上述命令时,wrangler 会要求先完成 Cloudflare 账户登录与项目选择,随后交互式地读取密钥值。密钥名必须与 src/index.js 中解构的环境变量名完全一致,Worker 才能正确取到值。仓库中的配套课程示例 with-cloudflare-workers-kv 使用完全相同的 SUPABASE_URL / SUPABASE_PUBLISHABLE_KEY 命名约定,说明这是一套被反复验证的既定实践。
第六步:发布部署
完成本地验证并注入密钥后,发布 Worker:
npx wrangler publish
发布后 Worker 即运行于 Cloudflare 边缘网络,任何对 Worker 路由的 HTTP 请求都会触发 fetch 处理器,实时查询 Supabase 的 articles 表并把数据以 application/json 响应返回。仓库 package.json 中的 deploy 脚本封装的就是这条命令。
完整调用链小结
把整个请求生命周期串起来看:
- 客户端请求到达 Cloudflare 边缘,触发 Worker 的
fetch处理器; - wrangler 注入的 secrets 通过
env绑定对象进入函数作用域; createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY)完成 Supabase 客户端初始化;supabase.from('articles').select('*')向 Supabase 项目发起查询,读取 Postgres 中articles表的记录;JSON.stringify(data)序列化查询结果,配合Content-Type: application/json响应头封装为Response返回给调用方。
从源码结构可以进一步推断该架构的扩展方向:若需要“先返回响应、再后台刷新缓存”的体验,可参考仓库中的 with-cloudflare-workers-kv 示例,借助 Workers 的 context.waitUntil 在响应返回后继续更新 KV 缓存——这与本示例共用同一套 Supabase 客户端初始化与密钥注入模式,可作为继续深入学习的下一站。
需要注意的边界
- 密钥定位:
SUPABASE_PUBLISHABLE_KEY(Anon Key)设计上允许暴露在客户端与边缘代码中,但它仍受网关与数据库 RLS 策略约束;切勿把高权限的service_role密钥放入 Worker 前端代码。 - 运行时差异:示例锁定的 wrangler 版本为
2.20.1、compatibility_date 为2022-07-26。使用更新版本 wrangler 时,个别命令(如publish与dev)的行为可能存在差异,但 secret 注入、env绑定与fetch模块约定是稳定的核心模型。 - 示例用途:该目录是一个教学性质的最小示例,未包含鉴权、错误处理与分页逻辑;投入生产前应补充
data为空的兜底、查询失败的状态码返回以及基于 RLS 的数据可见性控制。
通过本示例可以看到,借助 @supabase/supabase-js 与 wrangler 的 secrets 机制,把 Supabase 数据查询下沉到 Cloudflare Worker 仅需一个入口文件即可完成。读者可直接在仓库中对照 README.md、src/index.js 与 wrangler.toml 三个文件进行实践。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00