Supabase 开源后端:PostgreSQL 驱动的全栈平台
Supabase 开源 Firebase 替代方案:从零掌握 PostgreSQL 驱动的全栈平台
什么是 Supabase?
Supabase 是一个开源的 Firebase 替代方案,为现代应用提供完整的后端服务。它的口号是“用几天而不是几个月构建应用”,核心是以 PostgreSQL 数据库为引擎,将数据库、实时订阅、身份验证、文件存储、边缘函数等功能整合为一个统一平台。
与 Firebase 最大的不同在于:Supabase 完全开源,你可以将其部署在自己的服务器上,完全控制数据;同时它基于成熟的关系型数据库,允许你使用 SQL 的完整能力,而不是被锁在专有的 NoSQL 结构中。
为什么选择 Supabase 替代 Firebase?
1. 开源与数据自主权
Firebase 是 Google 的闭源服务,数据存储在 Google 云端,迁移困难。Supabase 的所有组件均可自托管,你可以随时将数据和项目导出,完全避免供应商锁定。
2. 关系型数据库的强大能力
Firebase Firestore 是文档型 NoSQL 数据库,很多复杂查询难以实现。Supabase 底层的 PostgreSQL 支持:
- 高级联接、聚合、窗口函数
- 完整的 ACID 事务
- 丰富的扩展生态(如 PostGIS 地理空间数据、pgvector 向量搜索)
- 行级安全策略 (RLS) 实现细粒度权限控制
3. 实时功能开箱即用
Supabase 通过 PostgreSQL 的逻辑复制将数据库变更以 WebSocket 推送出去,实现实时数据同步。你无需额外配置,只需开启复制并订阅通道即可。
4. 认证与第三方登录简单集成
内置支持邮箱/密码登录、Magic Link、手机验证,以及 Google、GitHub、Azure 等数十种 OAuth 提供者,且与数据库中的用户表自动关联。
5. 价格友好,可预测的成本
免费额度慷慨:每月 500 MB 数据库空间、5 GB 带宽、50,000 月活跃用户。Pro 计划按使用量付费,没有“烧钱”式的无上限计费。
Supabase 核心功能概览
数据库 (PostgreSQL)
- 完全托管的 PostgreSQL,可随时通过
psql或其它工具直接连接 - 内置可视化 SQL 编辑器与表管理界面
- 支持触发器、数据库函数、扩展
- 行级安全策略 (RLS):在数据库层级实施访问控制,前端直接查询也能保证安全
身份认证 (Auth)
- 提供 RESTful API 和客户端库,开箱即用
- 支持邮箱、电话、魔法链接、OAuth 等登录方式
- JWT 令牌与数据库用户表深度集成
- 自定义 SMTP 邮件服务与模板
文件存储 (Storage)
- 兼容 S3 的对象存储,用于存放图片、视频等用户生成内容
- 支持公开/私有存储桶,行级安全同样适用
实时订阅 (Realtime)
- 基于 PostgreSQL 复制,订阅指定表的变更(插入、更新、删除)
- 通过 WebSocket 推送,延迟极低
- 可配合 RLS 确保客户端只接收有权查看的数据
边缘函数 (Edge Functions)
- 基于 Deno 的 serverless 函数,全球分布式执行
- 适用于 Webhook 处理、敏感逻辑、第三方 API 代理
向量与 AI (pgvector)
- 内置 pgvector 扩展,支持向量存储和相似度搜索
- 可快速构建语义搜索、推荐系统、AI 知识库
快速上手:创建你的第一个 Supabase 项目
步骤 1:注册并创建项目
访问 supabase.com 使用 GitHub 账号登录。点击“New project”,填写项目名称、数据库密码,并选择一个离用户最近的区域。
项目初始化需要约 2 分钟,完成后你会进入仪表盘。
步骤 2:设计数据库表
在左侧菜单进入 “Table Editor”,点击 “New table” 创建一个 posts 表,字段示意:
id:uuid或int8,主键,默认自动生成title:text,非空content:textuser_id:uuid,关联到auth.users表created_at:timestamptz,默认now()
保存后,可以直接在 “SQL Editor” 中用标准 SQL 操作:
SELECT * FROM posts WHERE created_at > now() - interval '7 days';
步骤 3:启用行级安全 (RLS) 并制定策略
进入 “Authentication / Policies”,为 posts 表启用 RLS。然后新建一个策略:
- 策略名称:
允许用户读取所有公开文章 - 操作:
SELECT - 使用表达式:
true(所有登录用户可读) - 目标角色:
authenticated
再新建一个策略,限制只有作者本人可以插入:
- 操作:
INSERT - 使用表达式:
auth.uid() = user_id
这就实现了数据库级权限,即使用 API 直接调用也无法绕过。
步骤 4:在前端项目中集成 Supabase
安装客户端库(示例使用 JavaScript/TypeScript):
npm install @supabase/supabase-js
初始化:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
'https://your-project-id.supabase.co',
'public-anon-key'
)
查询文章:
const { data, error } = await supabase
.from('posts')
.select('*')
.order('created_at', { ascending: false })
插入需认证的文章(用户已通过 auth.signIn 登录后):
const { data, error } = await supabase
.from('posts')
.insert([{ title: 'Hello World', content: 'My first post' }])
实时订阅:
const channel = supabase
.channel('public:posts')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'posts' },
payload => { console.log('New post:', payload.new) }
)
.subscribe()
步骤 5:添加用户认证
使用内置 UI 组件或 API 实现登录:
// 邮箱注册
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'secure-password'
})
// OAuth 登录 (以 GitHub 为例)
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github'
})
登录后,客户端库会自动将 JWT 附加到后续请求,配合 RLS 自动过滤数据。
步骤 6:使用存储存放文件
创建存储桶并上传文件:
// 上传头像到 'avatars' 存储桶
const { data, error } = await supabase.storage
.from('avatars')
.upload('public/avatar1.png', file)
// 获取公开链接
const { data: { publicUrl } } = supabase.storage
.from('avatars')
.getPublicUrl('public/avatar1.png')
存储桶同样支持 RLS 策略,比如只允许用户上传到自己的文件夹。
Supabase 与 Firebase 功能对比
| 功能 | Supabase | Firebase |
|---|---|---|
| 数据库 | PostgreSQL (关系型) | Firestore (文档型) 或 Realtime Database (NoSQL) |
| 实时更新 | 基于 Postgres 复制,支持自定义筛选 | 基于 SDK 监听,受限于数据结构 |
| 身份认证 | 多种登录方式,JWT 与数据库用户无缝对接 | 认证与 Firestore 深度绑定,自定义较复杂 |
| 文件存储 | S3 兼容存储,RLS 保护 | Cloud Storage,依赖 Security Rules |
| 后端函数 | Deno 边缘函数 (Edge Functions) | Cloud Functions (Node.js) |
| 开源性 | 完全开源,可自托管 | 闭源,仅云服务 |
| SQL 查询 | 完全支持 | 有限制,需要使用 SDK 或复合查询 |
| 供应商锁定 | 低,可导出 SQL 在任何 PostgreSQL 运行 | 高,数据格式和逻辑迁移困难 |
| 免费额度 | 500 MB 数据库 + 5 GB 带宽 | 1 GB 存储 + 10 GB/月下载 (Firestore) |
深入特性:行级安全策略实战
传统后端架构中,我们常在应用层写大量代码来校验用户是否有权访问某条数据。Supabase 的 RLS 将这部分下移到数据库,更安全也更高效。
示例:多租户博客仅允许作者编辑自己的文章
-- 启用 RLS
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 策略:所有用户可查看已发布文章
CREATE POLICY "查看已发布" ON posts
FOR SELECT
USING (status = 'published');
-- 策略:作者本人可查看和修改自己的所有文章
CREATE POLICY "作者管理自己的文章" ON posts
FOR ALL
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
FOR ALL 表示 SELECT / INSERT / UPDATE / DELETE 都适用。USING 检查已有行,WITH CHECK 检查即将写入的行。
RLS 策略让你无需编写 API 端点来进行权限检查,甚至可以直接从客户端安全查询数据库。
高级玩法:数据库函数与触发器
Supabase 鼓励你利用 PostgreSQL 的计算能力,将业务逻辑封装在数据库函数中,再通过 supabase.rpc() 调用。
创建函数实现点赞更新并返回新计数:
CREATE OR REPLACE FUNCTION increment_likes(post_id uuid)
RETURNS integer AS $$
DECLARE
new_count integer;
BEGIN
UPDATE posts SET likes = likes + 1 WHERE id = post_id
RETURNING likes INTO new_count;
RETURN new_count;
END;
$$ LANGUAGE plpgsql;
前端调用:
const { data, error } = await supabase.rpc('increment_likes', { post_id: '...' })
这样可保证原子性,避免并发问题。
自托管 vs. 云托管
如果你需要完全控制数据,可以使用 Supabase CLI 在本地开发,并将项目部署到自己的服务器。核心组件都通过 Docker 编排,包括 Kong API 网关、PostgreSQL、GoTrue (认证)、Realtime 等。
# 安装 CLI 后初始化本地环境
supabase init
supabase start
本地环境包含完整的服务,可以离线开发。生产环境部署推荐使用 Kubernetes 或 Docker Compose,社区提供详细指南。
常见陷阱与最佳实践
- 不要关闭 RLS:新手常因调试困难而直接禁用行级安全,这会导致数据裸奔。
- 使用环境变量管理密钥:JWT 密钥、匿名公钥、服务密钥需严格区分,服务密钥绝对不能暴露给客户端。
- 合理使用数据类型:利用
jsonb存储半结构化数据,但避免滥用——关系型模型的优势在于结构化数据。 - 优化订阅:实时订阅要加适当的过滤条件,避免全表推送占用过多带宽。
- 定期备份:虽然 Supabase 每天自动备份,自托管环境需自行配置备份策略。
总结
Supabase 重新定义了开发者与数据库的关系——它让 PostgreSQL 不再只是被后端保护起来的数据仓库,而成为应用安全的基石。借助行级安全、实时订阅和丰富的认证方式,你可以用更简洁的代码构建出安全、实时的全栈应用,同时享受开源带来的自由。无论是个人项目、初创产品还是企业级系统,Supabase 都提供了一个极具吸引力的 Firebase 替代方案。
下一步你可以:
- 尝试官方教程 Supabase Docs
- 克隆示例项目 GitHub 仓库
- 加入 Discord 社区讨论最佳实践
用 SQL 的优雅解决你曾困在 NoSQL 里的难题,从今天开始用 Supabase 加速你的开发。