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
llms.txt
Wie man Echtzeit-Chat-Anwendungen mit Supabase erstellt - HeapSoft