Come Creare Applicazioni di Chat in Tempo Reale con Supabase
Impara a costruire applicazioni di chat in tempo reale scalabili utilizzando Supabase con abbonamenti WebSocket, trasmissione di messaggi e funzionalità di presenza dell'utente. Perfetto per le applicazioni web moderne che richiedono comunicazione istantanea.
Costruire applicazioni di chat in tempo reale non è mai stato più facile con le potenti capacità in tempo reale di Supabase. In questa guida completa, passeremo attraverso la creazione di un'applicazione di chat pronta per la produzione che sfrutta le sottoscrizioni WebSocket di Supabase, i trigger PostgreSQL e l'autenticazione integrata. Che tu stia costruendo una chat di supporto al cliente, uno strumento di collaborazione di squadra o un'applicazione di messaggistica sociale, questo tutorial ti fornirà il fondamento che ti serve.
Perché Scegliere Supabase per la Chat in Tempo Reale?
Supabase si distingue come la piattaforma ideale per le applicazioni di chat in tempo reale grazie alle sue sottoscrizioni in tempo reale native PostgreSQL, alla sicurezza a livello di riga e all'integrazione dell'autenticazione senza soluzione di continuità. A differenza delle soluzioni tradizionali che richiedono server WebSocket separati e una gestione dello stato complessa, Supabase fornisce tutto fuori dalla scatola.
- Sottoscrizioni in tempo reale integrate con trigger PostgreSQL
- Sicurezza a livello di riga per la privacy dei messaggi e il controllo degli accessi
- Autenticazione utente integrata con fornitori sociali
- Scalatura automatica senza gestione dell'infrastruttura
- Supporto completo di TypeScript con tipi generati
Configurazione dello Schema del Database
Prima, progettiamo il nostro schema di database per la chat. Avremo bisogno di tabelle per le stanze della chat, i messaggi e il tracciamento della presenza degli utenti.
- Stanze di chat o canali
- Messaggi chat individuali
- Traccia lo stato online/offline
- Appartenenza alla stanza e permessi
-- Crea la tabella delle chat room
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()
);
-- Crea la tabella dei messaggi
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()
);
-- Crea la tabella della presenza degli utenti
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'
);
-- Crea la tabella dei membri della stanza
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)
);Implementazione della Sicurezza a Livello di Riga
La sicurezza è fondamentale per le applicazioni di chat. Implementiamo la sicurezza a livello di riga (RLS) per garantire che gli utenti possano accedere solo ai messaggi delle stanze di cui sono membri.
- Abilita RLS su tutte le tabelle
- Gli utenti possono leggere i messaggi dalle stanze di cui sono membri
- Gli utenti possono inserire messaggi nelle stanze di cui sono membri
- Gli utenti possono accedere solo alle stanze di cui sono membri
-- Abilita RLS su tutte le tabelle
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;
-- Politica per la lettura dei messaggi
CREATE POLICY "Gli utenti possono leggere i messaggi dalle stanze di cui sono membri"
ON messages
FOR SELECT
USING (
room_id IN (
SELECT room_id FROM room_members
WHERE user_id = auth.uid()
)
);
-- Politica per l'inserimento dei messaggi
CREATE POLICY "Gli utenti possono inserire messaggi nelle stanze di cui sono membri"
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()
)
);
-- Politica per i membri della stanza
CREATE POLICY "Gli utenti possono vedere i membri della stanza delle stanze in cui si trovano"
ON room_members
FOR SELECT
USING (
room_id IN (
SELECT room_id FROM room_members
WHERE user_id = auth.uid()
)
);Impostazione delle sottoscrizioni in tempo reale
Ora implementiamo la funzionalità in tempo reale lato client utilizzando il client JavaScript di Supabase.
Imposta le sottoscrizioni ai messaggi per aggiornamenti in tempo reale:
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>
)
}Implementazione della Presenza dell'Utente
La presenza dell'utente mostra chi è online e quando gli utenti sono stati attivi l'ultima volta. Implementiamo questa funzione utilizzando la presenza in tempo reale di Supabase.
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
}Trasmissione e Gestione dei Messaggi
Implementiamo l'invio di messaggi e gestiamo diversi tipi di messaggi, inclusi testo, immagini e file.
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')
}Suggerimenti per l'Ottimizzazione delle Prestazioni
Per garantire che la tua applicazione di chat funzioni bene su larga scala, prendi in considerazione queste strategie di ottimizzazione:
- Implementa la paginazione dei messaggi per evitare di caricare troppi messaggi contemporaneamente
- Aggiungi indici al database su colonne frequentemente interrogate (room_id, created_at)
- Utilizza la compressione dei messaggi per contenuti di testo grandi
- Implementa la pulizia automatica dei vecchi messaggi e file
- Memorizza nella cache i profili degli utenti e i metadati della stanza per ridurre le query del database
-- 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);Considerazioni sulla Produzione
Prima di implementare la tua applicazione di chat in produzione, considera questi fattori importanti:
- Implementa la limitazione del tasso per prevenire spam e abusi
- Aggiungi funzionalità di moderazione dei contenuti e di segnalazione
- Imposta backup automatici del database
- Monitorizza in tempo reale il conteggio delle connessioni e il volume dei messaggi
- Pianifica per lo scaling orizzontale man mano che la tua base di utenti cresce
Conclusione
La costruzione di applicazioni di chat in tempo reale con Supabase fornisce una base robusta e scalabile per le moderne funzionalità di comunicazione. Con abbonamenti in tempo reale integrati, sicurezza a livello di riga e autenticazione senza soluzione di continuità, puoi concentrarti sulla creazione di ottime esperienze utente piuttosto che sulla gestione dell'infrastruttura. La combinazione della affidabilità di PostgreSQL e delle capacità in tempo reale di Supabase lo rende la scelta ideale per le applicazioni di chat su qualsiasi scala.
Pronto a Creare lei Applicazioni?
Il nostro team di esperti Supabase svizzeri può aiutarti a progettare e implementare schemi di database type-safe per il tuo prossimo progetto. Dalla progettazione iniziale dello schema allo sviluppo completo dell'applicazione, abbiamo tutto coperto.
Ottieni Consulenza Esperta