Supabase实战指南:用开源BaaS构建现代全栈应用
Supabase是Firebase的开源替代方案,基于PostgreSQL构建,提供了数据库、认证、实时订阅、存储和Edge Functions等完整的后端服务。
快速开始
bash
npx create-next-app@latest my-blog --typescript --tailwind
cd my-blog
npm install @supabase/supabase-js @supabase/ssr数据库与Row Level Security
RLS是Supabase安全模型的核心。通过PostgreSQL策略,在数据库层面控制数据访问:
sql
-- 创建posts表
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
author_id UUID REFERENCES auth.users(id),
created_at TIMESTAMPTZ DEFAULT now(),
published BOOLEAN DEFAULT false
);
-- 启用RLS
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 所有人可以读已发布的文章
CREATE POLICY "Public can read published posts"
ON posts FOR SELECT
USING (published = true);
-- 作者可以管理自己的文章
CREATE POLICY "Authors manage own posts"
ON posts FOR ALL
USING (auth.uid() = author_id)
WITH CHECK (auth.uid() = author_id);认证系统
typescript
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}
// components/LoginForm.tsx
'use client';
import { createClient } from '@/lib/supabase/client';
export function LoginForm() {
const supabase = createClient();
async function signInWithGithub() {
await supabase.auth.signInWithOAuth({
provider: 'github',
options: { redirectTo: `${location.origin}/auth/callback` },
});
}
async function signInWithMagicLink(email: string) {
const { error } = await supabase.auth.signInWithOtp({
email,
options: { emailRedirectTo: `${location.origin}/auth/callback` },
});
}
return (
<div>
<button onClick={signInWithGithub}>GitHub登录</button>
<MagicLinkForm onSubmit={signInWithMagicLink} />
</div>
);
}实时订阅
typescript
// 订阅posts表的实时变化
const supabase = createClient();
const channel = supabase
.channel('posts-changes')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'posts' },
(payload) => {
console.log('Change received:', payload.eventType);
console.log('New data:', payload.new);
}
)
.subscribe();
// 组件卸载时取消订阅
// channel.unsubscribe();文件存储
typescript
// 上传头像
async function uploadAvatar(userId: string, file: File) {
const supabase = createClient();
const fileExt = file.name.split('.').pop();
const filePath = `${userId}/avatar.${fileExt}`;
const { data, error } = await supabase.storage
.from('avatars')
.upload(filePath, file, { upsert: true });
if (error) throw error;
// 获取公开URL
const { data: { publicUrl } } = supabase.storage
.from('avatars')
.getPublicUrl(filePath);
return publicUrl;
}实战:文章搜索
typescript
// app/api/search/route.ts
import { createClient } from '@/lib/supabase/server';
import { NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const query = request.nextUrl.searchParams.get('q');
if (!query) return Response.json({ error: 'Missing query' }, { status: 400 });
const supabase = await createClient();
const { data, error } = await supabase
.from('posts')
.select('id, title, slug, excerpt')
.eq('published', true)
.or(`title.ilike.%${query}%,content.ilike.%${query}%`)
.order('created_at', { ascending: false })
.limit(20);
return Response.json({ data });
}Edge Functions
typescript
// supabase/functions/send-welcome-email/index.ts
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
Deno.serve(async (req) => {
const { user } = await req.json();
// 发送欢迎邮件
await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('RESEND_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'noreply@myapp.com',
to: user.email,
subject: '欢迎加入!',
html: '<h1>欢迎!</h1><p>感谢注册。</p>',
}),
});
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' },
});
});总结
Supabase提供了生产级的后端基础设施,开源且自托管友好。其核心优势:
- PostgreSQL — 世界上最先进的开源数据库
- RLS — 数据库级别的安全策略
- 实时 — 原生WebSocket支持
- 开源 — 无供应商锁定,可自托管
- 开发者体验 — 自动生成API,优秀的SDK