Comment construire des applications de chat en temps réel avec Supabase

Apprenez à construire des applications de chat en temps réel évolutives en utilisant Supabase avec des abonnements WebSocket, la diffusion de messages et les fonctionnalités de présence utilisateur. Parfait pour les applications web modernes nécessitant une communication instantanée.

Construire des applications de chat en temps réel n'a jamais été aussi facile avec les puissantes capacités en temps réel de Supabase. Dans ce guide complet, nous passerons à travers la création d'une application de chat prête pour la production qui exploite les abonnements WebSocket de Supabase, les déclencheurs PostgreSQL et l'authentification intégrée. Que vous construisiez un chat de support client, un outil de collaboration d'équipe ou une application de messagerie sociale, ce tutoriel vous donnera la base dont vous avez besoin.

Pourquoi choisir Supabase pour le chat en temps réel?

Supabase se distingue comme la plateforme idéale pour les applications de chat en temps réel grâce à ses abonnements PostgreSQL en temps réel natifs, sa sécurité au niveau des lignes et son intégration d'authentification transparente. Contrairement aux solutions traditionnelles qui nécessitent des serveurs WebSocket séparés et une gestion d'état complexe, Supabase fournit tout dès le départ.

  • Abonnements en temps réel intégrés avec des déclencheurs PostgreSQL
  • Sécurité au niveau des lignes pour la confidentialité des messages et le contrôle d'accès
  • Authentification utilisateur intégrée avec des fournisseurs sociaux
  • Mise à l'échelle automatique sans gestion d'infrastructure
  • Prise en charge complète de TypeScript avec des types générés

Configuration du schéma de la base de données

Tout d'abord, concevons notre schéma de base de données pour le chat. Nous aurons besoin de tables pour les salles de chat, les messages et le suivi de la présence des utilisateurs.

  • Salles de chat ou canaux
  • Messages de chat individuels
  • Suivre le statut en ligne/hors ligne
  • Adhésion à la salle et permissions
-- Créer la table des salles de chat
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()
);

-- Créer la table des messages
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()
);

-- Créer la table de présence utilisateur
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'
);

-- Créer la table des membres de salle
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)
);

Mise en œuvre de la sécurité au niveau des lignes

La sécurité est cruciale pour les applications de chat. Mettons en œuvre la sécurité au niveau des lignes (RLS) pour garantir que les utilisateurs ne peuvent accéder qu'aux messages des salles dont ils sont membres.

  • Activer RLS sur toutes les tables
  • Les utilisateurs peuvent lire les messages des salles dont ils sont membres
  • Les utilisateurs peuvent insérer des messages dans les salles dont ils sont membres
  • Les utilisateurs ne peuvent accéder qu'aux salles dont ils sont membres
-- Activer RLS sur toutes les tables
ALTER TABLE chat_rooms ACTIVATE ROW LEVEL SECURITY;
ALTER TABLE messages ACTIVATE ROW LEVEL SECURITY;
ALTER TABLE room_members ACTIVATE ROW LEVEL SECURITY;
ALTER TABLE user_presence ACTIVATE ROW LEVEL SECURITY;

-- Politique pour lire les messages
CREATE POLICY "Les utilisateurs peuvent lire les messages des salles dont ils sont membres" 
ON messages 
FOR SELECT 
USING (
  room_id IN (
    SELECT room_id FROM room_members 
    WHERE user_id = auth.uid()
  )
);

-- Politique pour insérer des messages
CREATE POLICY "Les utilisateurs peuvent insérer des messages dans les salles dont ils sont membres" 
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()
  )
);

-- Politique pour les membres de la salle
CREATE POLICY "Les utilisateurs peuvent voir les membres de la salle dans laquelle ils se trouvent"  
ON room_members  
FOR SELECT  
USING (  
  room_id IN (  
    SELECT room_id FROM room_members   
    WHERE user_id = auth.uid()  
  )  
);

Configuration des abonnements en temps réel

Maintenant, mettons en œuvre la fonctionnalité en temps réel côté client en utilisant le client JavaScript de Supabase.

Configurez des abonnements aux messages pour des mises à jour en temps réel:

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>
  )
}

Mise en œuvre de la présence de l'utilisateur

La présence de l'utilisateur indique qui est en ligne et quand les utilisateurs ont été actifs pour la dernière fois. Mettons en œuvre cette fonctionnalité en utilisant la présence en temps réel de 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
}

Diffusion et Gestion des Messages

Implémentons l'envoi de messages et gérons différents types de messages, y compris le texte, les images et les fichiers.

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')
}

Conseils d'Optimisation des Performances

Pour garantir que votre application de chat fonctionne bien à grande échelle, envisagez ces stratégies d'optimisation :

  • Mettez en œuvre la pagination des messages pour éviter de charger trop de messages à la fois
  • Ajoutez des index de base de données sur les colonnes fréquemment interrogées (room_id, created_at)
  • Utilisez la compression de messages pour les grands contenus textuels
  • Mettez en œuvre le nettoyage automatique des anciens messages et fichiers
  • Mettez en cache les profils d'utilisateurs et les métadonnées de la salle pour réduire les requêtes de base de données
-- 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);

Considérations de Production

Avant de déployer votre application de chat en production, prenez en compte ces facteurs importants :

  • Mettez en œuvre une limitation de débit pour prévenir le spam et les abus
  • Ajoutez des fonctionnalités de modération de contenu et de rapport
  • Mettez en place des sauvegardes automatiques de base de données
  • Surveillez en temps réel le nombre de connexions et le volume des messages
  • Prévoyez une mise à l'échelle horizontale au fur et à mesure que votre base d'utilisateurs grandit

Conclusion

La construction d'applications de chat en temps réel avec Supabase fournit une base robuste et évolutive pour les fonctionnalités modernes de communication. Avec des abonnements en temps réel intégrés, une sécurité au niveau des lignes et une authentification transparente, vous pouvez vous concentrer sur la création de grandes expériences utilisateur plutôt que sur la gestion de l'infrastructure. La combinaison de la fiabilité de PostgreSQL et des capacités en temps réel de Supabase en fait un choix idéal pour les applications de chat à n'importe quelle échelle.

Prêt à Créer votre Applications?

Notre équipe d'experts Supabase suisses peut vous aider à concevoir et implémenter des schémas de base de données type-safe pour votre prochain projet. De la conception initiale du schéma au développement complet de l'application, nous avons tout couvert.

Obtenir une Consultation Expert
llms.txt
Comment Construire des Applications de Chat en Temps Réel avec Supabase - HeapSoft