REST API vs GraphQL
拥有 20 多年历史的 REST 对决源自 Facebook 的 GraphQL。为移动应用后端选择 API 设计范式时,该如何取舍?
Google全面的移动应用开发平台
开源的Firebase替代方案——基于PostgreSQL,可自托管
| 分类 | Firebase | Supabase |
|---|---|---|
| 性能 | 9/10 | 9/10 |
| 学习难易度 | 8/10 | 7/10 |
| 生态系统 | 10/10 | 7/10 |
| 社区 | 9/10 | 8/10 |
| 就业市场 | 9/10 | 7/10 |
| 面向未来 | 7/10 | 9/10 |
// Firebase - 实时聊天消息
import FirebaseFirestore
import FirebaseAuth
import SwiftUI
@Observable
class ChatViewModel {
var messages: [Message] = []
private var listener: ListenerRegistration?
private let db = Firestore.firestore()
struct Message: Identifiable, Codable {
@DocumentID var id: String?
let senderId: String
let senderName: String
let text: String
let timestamp: Timestamp
}
func startListening(roomId: String) {
listener = db.collection("rooms")
.document(roomId)
.collection("messages")
.order(by: "timestamp", descending: false)
.limit(toLast: 50)
.addSnapshotListener { [weak self] snapshot, error in
guard let documents = snapshot?.documents else { return }
self?.messages = documents.compactMap {
try? $0.data(as: Message.self)
}
}
}
func sendMessage(text: String, roomId: String) async throws {
guard let user = Auth.auth().currentUser else { return }
let message = Message(
senderId: user.uid,
senderName: user.displayName ?? "匿名",
text: text,
timestamp: Timestamp()
)
try db.collection("rooms")
.document(roomId)
.collection("messages")
.addDocument(from: message)
}
func stopListening() { listener?.remove() }
}// Supabase - 用户帖子CRUD
import Supabase
import Foundation
struct Post: Codable, Identifiable {
let id: UUID
let userId: UUID
let title: String
let content: String
let createdAt: Date
enum CodingKeys: String, CodingKey {
case id, title, content
case userId = "user_id"
case createdAt = "created_at"
}
}
class PostRepository {
private let client = SupabaseClient(
supabaseURL: URL(string: ProcessInfo.processInfo.environment["SUPABASE_URL"]!)!,
supabaseKey: ProcessInfo.processInfo.environment["SUPABASE_ANON_KEY"]!
)
func fetchPosts() async throws -> [Post] {
try await client
.from("posts")
.select("*")
.order("created_at", ascending: false)
.limit(20)
.execute()
.value
}
func createPost(title: String, content: String) async throws -> Post {
let userId = try await client.auth.session.user.id
return try await client
.from("posts")
.insert(["user_id": userId.uuidString, "title": title, "content": content])
.select()
.single()
.execute()
.value
}
func subscribeToNewPosts(onNewPost: @escaping (Post) -> Void) -> RealtimeChannelV2 {
let channel = client.channel("public:posts")
channel.onPostgresChange(
InsertAction.self,
table: "posts"
) { change in
if let post = try? change.record.decode(as: Post.self) {
onNewPost(post)
}
}
Task { await channel.subscribe() }
return channel
}
}如果追求快速开发、卓越的iOS SDK和实时功能,Firebase实力强劲。如果需要关系型数据、SQL灵活性、开源特性以及担心供应商锁定问题,Supabase是更好的选择。2025年Supabase快速走向成熟,成为强有力的竞争者——尤其是pgvector集成为AI功能应用带来了明显优势。
获取免费咨询可以,但并不容易。Firestore的NoSQL结构需要转换为PostgreSQL schema,Auth用户需要迁移,Storage文件需要转移。这需要一个全面的迁移项目。