Skip to content

Supabase 完全指南

Supabase 是一款开源的 Firebase 替代方案,提供 PostgreSQL 数据库、认证、存储、实时订阅、Edge Functions 等完整后端能力。与 Firebase 不同,Supabase 基于 PostgreSQL,你可以使用标准 SQL,且可以自托管。

核心功能#

功能说明
Database托管的 PostgreSQL 数据库
Auth用户认证(邮箱、OAuth、Magic Link)
Storage文件存储(类似 S3)
Realtime数据库变更实时推送
Edge FunctionsServerless 函数(Deno 运行时)
AI & Vectors向量存储和 AI 集成

快速开始#

1. 创建项目#

  1. 访问 supabase.com
  2. 使用 GitHub 登录
  3. 点击「New Project」
  4. 填写项目名称和数据库密码
  5. 选择区域(推荐新加坡)

2. 获取连接信息#

项目设置 → API:

Project URL: https://xxx.supabase.co
anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
service_role key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

3. 安装 SDK#

Terminal window
npm install @supabase/supabase-js

4. 初始化客户端#

import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://xxx.supabase.co', 'your-anon-key')

数据库操作#

创建表#

使用 Table Editor 或 SQL Editor:

CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
content TEXT,
author_id UUID REFERENCES auth.users(id),
created_at TIMESTAMPTZ DEFAULT NOW()
);

启用 RLS#

Row Level Security(行级安全)是 Supabase 的核心安全机制:

-- 启用 RLS
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 允许所有人读取
CREATE POLICY "公开读取" ON posts
FOR SELECT USING (true);
-- 只允许作者编辑
CREATE POLICY "作者编辑" ON posts
FOR UPDATE USING (auth.uid() = author_id);

CRUD 操作#

查询

// 查询所有
const { data, error } = await supabase.from('posts').select('*')
// 条件查询
const { data } = await supabase
.from('posts')
.select('*')
.eq('author_id', userId)
.order('created_at', { ascending: false })
.limit(10)
// 关联查询
const { data } = await supabase.from('posts').select(`
*,
author:users(name, avatar)
`)

插入

const { data, error } = await supabase
.from('posts')
.insert({ title: 'Hello', content: 'World' })
.select()

更新

const { data, error } = await supabase
.from('posts')
.update({ title: 'Updated' })
.eq('id', postId)
.select()

删除

const { error } = await supabase.from('posts').delete().eq('id', postId)

用户认证#

邮箱注册登录#

// 注册
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'password123',
})
// 登录
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'password123',
})
// 登出
await supabase.auth.signOut()

OAuth 登录#

// GitHub 登录
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
options: {
redirectTo: 'https://your-app.com/callback',
},
})
// Google 登录
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
})

监听认证状态#

supabase.auth.onAuthStateChange((event, session) => {
if (event === 'SIGNED_IN') {
console.log('用户已登录', session.user)
}
if (event === 'SIGNED_OUT') {
console.log('用户已登出')
}
})

获取当前用户#

const {
data: { user },
} = await supabase.auth.getUser()

文件存储#

创建存储桶#

Storage → New Bucket → 设置名称和权限

上传文件#

const file = event.target.files[0]
const { data, error } = await supabase.storage
.from('avatars')
.upload(`${userId}/avatar.png`, file, {
cacheControl: '3600',
upsert: true,
})

获取公开 URL#

const { data } = supabase.storage
.from('avatars')
.getPublicUrl('path/to/file.png')
console.log(data.publicUrl)

下载文件#

const { data, error } = await supabase.storage
.from('documents')
.download('path/to/file.pdf')

存储策略#

配置 RLS 控制文件访问:

-- 允许用户上传到自己的文件夹
CREATE POLICY "用户上传" ON storage.objects
FOR INSERT WITH CHECK (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);

实时订阅#

监听表变化#

const channel = supabase
.channel('posts-changes')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'posts' },
(payload) => {
console.log('变化:', payload)
}
)
.subscribe()
// 取消订阅
channel.unsubscribe()

监听特定事件#

// 只监听插入
.on('postgres_changes', { event: 'INSERT', ... })
// 只监听更新
.on('postgres_changes', { event: 'UPDATE', ... })
// 只监听删除
.on('postgres_changes', { event: 'DELETE', ... })

广播消息#

// 发送
const channel = supabase.channel('room-1')
channel.send({
type: 'broadcast',
event: 'message',
payload: { text: 'Hello!' },
})
// 接收
channel.on('broadcast', { event: 'message' }, (payload) => {
console.log(payload)
})

Edge Functions#

创建函数#

Terminal window
# 安装 Supabase CLI
npm install -g supabase
# 初始化
supabase init
# 创建函数
supabase functions new hello-world

函数代码#

supabase/functions/hello-world/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
serve(async (req) => {
const { name } = await req.json()
return new Response(JSON.stringify({ message: `Hello ${name}!` }), {
headers: { 'Content-Type': 'application/json' },
})
})

部署#

Terminal window
supabase functions deploy hello-world

调用#

const { data, error } = await supabase.functions.invoke('hello-world', {
body: { name: 'World' },
})

与框架集成#

Next.js#

Terminal window
npm install @supabase/ssr
lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export function createClient() {
const cookieStore = cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value
},
},
}
)
}

React#

// 使用 Context 提供 Supabase 客户端
import { createContext, useContext } from 'react'
const SupabaseContext = createContext(supabase)
export function useSupabase() {
return useContext(SupabaseContext)
}

自托管#

Supabase 完全开源,可自托管:

Terminal window
# 克隆仓库
git clone https://github.com/supabase/supabase
cd supabase/docker
# 配置环境变量
cp .env.example .env
# 启动服务
docker compose up -d

定价#

计划价格特点
Free$0/月500MB 数据库,1GB 存储
Pro$25/月8GB 数据库,100GB 存储
Team$599/月无限项目,优先支持

免费计划足够个人项目使用。

Supabase vs Firebase#

特性SupabaseFirebase
数据库PostgreSQLNoSQL
查询语言SQL专有 API
开源
自托管
实时订阅
定价模式按资源按使用量

选择建议

最佳实践#

1. 始终启用 RLS#

ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;

2. 使用 TypeScript 类型#

Terminal window
npx supabase gen types typescript --project-id your-project > types/supabase.ts
import { Database } from './types/supabase'
const supabase = createClient<Database>(url, key)

3. 环境变量安全#

# 客户端使用 anon key
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
# 服务端使用 service_role key
SUPABASE_SERVICE_ROLE_KEY=...

参考资料#