Wie man Echtzeit-Chat-Anwendungen mit Supabase erstellt
Lernen Sie, skalierbare Echtzeit-Chat-Anwendungen mit Supabase zu erstellen, die WebSocket-Abonnements, Nachrichtenübertragung und Benutzerpräsenzfunktionen nutzen. Perfekt für moderne Webanwendungen, die eine sofortige Kommunikation erfordern.
Der Aufbau von Echtzeit-Chat-Anwendungen war noch nie einfacher mit den leistungsstarken Echtzeit-Fähigkeiten von Supabase. In diesem umfassenden Leitfaden werden wir durch die Erstellung einer produktionsreifen Chat-Anwendung führen, die Supabases WebSocket-Abonnements, PostgreSQL-Triggers und integrierte Authentifizierung nutzt. Ob Sie einen Kundensupport-Chat, ein Team-Kollaborationstool oder eine soziale Messaging-App erstellen, dieses Tutorial gibt Ihnen die Grundlage, die Sie benötigen.
Warum Supabase für Echtzeit-Chat wählen?
Supabase zeichnet sich als ideale Plattform für Echtzeit-Chat-Anwendungen aus, dank seiner nativen PostgreSQL-Echtzeit-Abonnements, der zeilenbasierten Sicherheit und der nahtlosen Authentifizierungsintegration. Im Gegensatz zu traditionellen Lösungen, die separate WebSocket-Server und eine komplexe Statusverwaltung erfordern, bietet Supabase alles aus einer Hand.
- Eingebaute Echtzeit-Abonnements mit PostgreSQL-Triggern
- Datensatz-Ebene-Sicherheit für Nachrichtenprivatsphäre und Zugriffskontrolle
- Integrierte Benutzerauthentifizierung mit sozialen Anbietern
- Automatisches Skalieren ohne Infrastrukturverwaltung
- Vollständige TypeScript-Unterstützung mit generierten Typen
Einrichten des Datenbankschemas
Zuerst entwerfen wir unser Chat-Datenbankschema. Wir benötigen Tabellen für Chaträume, Nachrichten und die Nachverfolgung der Benutzerpräsenz.
- Chaträume oder Kanäle
- Einzelnachrichten im Chat
- Online/Offline-Status verfolgen
- Mitgliedschaft im Raum und Berechtigungen
-- Chat-Räume Tabelle erstellen
CREATE TABLE chat_rooms (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
created_by UUID REFERENCES auth.users(id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Nachrichten Tabelle erstellen
CREATE TABLE messages (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
room_id UUID REFERENCES chat_rooms(id) ON DELETE CASCADE,
user_id UUID REFERENCES auth.users(id),
content TEXT NOT NULL,
message_type TEXT DEFAULT 'text' CHECK (message_type IN ('text', 'image', 'file')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Benutzerpräsenz Tabelle erstellen
CREATE TABLE user_presence (
user_id UUID REFERENCES auth.users(id) PRIMARY KEY,
last_seen TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
is_online BOOLEAN DEFAULT false,
status TEXT DEFAULT 'offline'
);
-- Raummitglieder Tabelle erstellen
CREATE TABLE room_members (
room_id UUID REFERENCES chat_rooms(id) ON DELETE CASCADE,
user_id UUID REFERENCES auth.users(id),
role TEXT DEFAULT 'member' CHECK (role IN ('owner', 'admin', 'member')),
joined_at TIMESTAMP WITH TIME ZONEDEFAULT NOW(),
PRIMARY KEY (room_id, user_id)
);Implementierung der zeilenbasierten Sicherheit
Sicherheit ist entscheidend für Chat-Anwendungen. Lassen Sie uns die zeilenbasierte Sicherheit (RLS) implementieren, um sicherzustellen, dass Benutzer nur auf Nachrichten aus Räumen zugreifen können, in denen sie Mitglieder sind.
- Aktivieren Sie RLS auf allen Tabellen
- Benutzer können Nachrichten aus Räumen lesen, in denen sie Mitglieder sind.
- Benutzer können Nachrichten in Räume einfügen, in denen sie Mitglieder sind.
- Benutzer können nur auf Räume zugreifen, in denen sie Mitglieder sind.
-- Aktivieren Sie RLS auf allen Tabellen
ALTER TABLE chat_rooms ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE room_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_presence ENABLE ROW LEVEL SECURITY;
-- Richtlinie zum Lesen von Nachrichten
CREATE POLICY "Benutzer können Nachrichten aus Räumen lesen, in denen sie Mitglieder sind"
ON messages
FOR SELECT
USING (
room_id IN (
SELECT room_id FROM room_members
WHERE user_id = auth.uid()
)
);
-- Richtlinie zum Einfügen von Nachrichten
CREATE POLICY "Benutzer können Nachrichten in Räume einfügen, in denen sie Mitglieder sind"
ON messages
FOR INSERT
WITH CHECK (
user_id = auth.uid() AND
room_id IN (
SELECT room_id FROM room_members
WHERE user_id = auth.uid()
)
);
-- Richtlinie für Raummitglieder
CREATE POLICY "Benutzer können die Raummitglieder der Räume sehen, in denen sie sich befinden"
ON room_members
FOR SELECT
USING (
room_id IN (
SELECT room_id FROM room_members
WHERE user_id = auth.uid()
)
);Einrichten von Echtzeit-Abonnements
Lassen Sie uns nun die Client-seitige Echtzeitfunktionalität mit Supabase's JavaScript-Client implementieren.
Richten Sie Nachrichtenabonnements für Echtzeit-Updates ein:
import { useEffect, useState } from 'react'
import { supabase } from './supabase'
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([])
useEffect(() => {
// Fetch initial messages
const fetchMessages = async () => {
const { data } = await supabase
.from('messages')
.select('*')
.eq('room_id', roomId)
.order('created_at', { ascending: true })
setMessages(data || [])
}
fetchMessages()
// Subscribe to new messages
const subscription = supabase
.channel(`room:${roomId}`)
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: `room_id=eq.${roomId}`
},
(payload) => {
setMessages(prev => [...prev, payload.new])
}
)
.subscribe()
return () => {
subscription.unsubscribe()
}
}, [roomId])
return (
<div className="chat-room">
{/* Chat UI implementation */}
</div>
)
}Implementierung von Benutzerpräsenz
Die Benutzerpräsenz zeigt, wer online ist und wann die Benutzer zuletzt aktiv waren. Lassen Sie uns diese Funktion mit der Echtzeit-Präsenz von Supabase implementieren.
import { useEffect, useState } from 'react'
function useUserPresence(roomId) {
const [onlineUsers, setOnlineUsers] = useState([])
useEffect(() => {
const channel = supabase.channel(`presence:${roomId}`)
channel
.on('presence', { event: 'sync' }, () => {
const state = channel.presenceState()
const users = Object.keys(state)
setOnlineUsers(users)
})
.on('presence', { event: 'join' }, ({ key }) => {
setOnlineUsers(prev => [...prev, key])
})
.on('presence', { event: 'leave' }, ({ key }) => {
setOnlineUsers(prev => prev.filter(id => id !== key))
})
.subscribe(async (status) => {
if (status === 'SUBSCRIBED') {
await channel.track({
user_id: user?.id,
online_at: new Date().toISOString(),
})
}
})
return () => {
channel.unsubscribe()
}
}, [roomId])
return onlineUsers
}Nachrichtenübertragung und -verarbeitung
Lassen Sie uns das Senden von Nachrichten implementieren und verschiedene Nachrichtentypen behandeln, einschließlich Text, Bilder und Dateien.
async function sendMessage(roomId, content, messageType = 'text') {
const { data, error } = await supabase
.from('messages')
.insert({
room_id: roomId,
user_id: user?.id,
content,
message_type: messageType
})
.select()
if (error) {
console.error('Error sending message:', error)
return null
}
return data[0]
}
// Handle file uploads
async function sendFileMessage(roomId, file) {
// Upload file to Supabase Storage
const fileName = `${Date.now()}-${file.name}`
const { data: uploadData, error: uploadError } = await supabase.storage
.from('chat-files')
.upload(fileName, file)
if (uploadError) {
console.error('Error uploading file:', uploadError)
return
}
// Get public URL
const { data: { publicUrl } } = supabase.storage
.from('chat-files')
.getPublicUrl(fileName)
// Send message with file URL
await sendMessage(roomId, publicUrl, 'file')
}Leistungsoptimierungstipps
Um sicherzustellen, dass Ihre Chat-Anwendung im großen Maßstab gut funktioniert, sollten Sie diese Optimierungsstrategien in Betracht ziehen:
- Implementieren Sie die Nachrichtenpaginierung, um zu vermeiden, dass zu viele Nachrichten auf einmal geladen werden.
- Fügen Sie Datenbankindizes zu häufig abgefragten Spalten hinzu (room_id, created_at)
- Verwenden Sie Nachrichtenkompression für großen Textinhalt
- Implementieren Sie die automatische Bereinigung alter Nachrichten und Dateien
- Benutzerprofile und Raum-Metadaten zwischenspeichern, um Datenbankabfragen zu reduzieren
-- Add indexes for better performance
CREATE INDEX idx_messages_room_created ON messages(room_id, created_at DESC);
CREATE INDEX idx_room_members_user ON room_members(user_id);
CREATE INDEX idx_messages_user ON messages(user_id);Produktionsüberlegungen
Bevor Sie Ihre Chat-Anwendung in die Produktion überführen, sollten Sie diese wichtigen Faktoren berücksichtigen:
- Implementieren Sie eine Geschwindigkeitsbegrenzung, um Spam und Missbrauch zu verhindern
- Fügen Sie Inhaltsmoderation und Berichtsfunktionen hinzu
- Richten Sie automatisierte Datenbanksicherungen ein
- Überwachen Sie Echtzeit-Verbindungsanzahlen und Nachrichtenvolumen
- Planen Sie eine horizontale Skalierung, wenn Ihre Benutzerbasis wächst
Schlussfolgerung
Der Aufbau von Echtzeit-Chat-Anwendungen mit Supabase bietet eine robuste, skalierbare Grundlage für moderne Kommunikationsfunktionen. Mit integrierten Echtzeit-Abonnements, zeilenbasierter Sicherheit und nahtloser Authentifizierung können Sie sich auf die Erstellung großartiger Benutzererlebnisse konzentrieren, anstatt Infrastruktur zu verwalten. Die Kombination aus der Zuverlässigkeit von PostgreSQL und den Echtzeit-Fähigkeiten von Supabase macht es zur idealen Wahl für Chat-Anwendungen jeder Größe.
Bereit, deine Anwendungen zu erstellen?
Unser Team von Schweizer Supabase-Experten kann Ihnen helfen, typsichere Datenbank-Schemas für Ihr nächstes Projekt zu entwerfen und zu implementieren. Vom ersten Schema-Design bis zur vollständigen Anwendungsentwicklung haben wir alles abgedeckt.
Expertenberatung erhalten