Mettre à jour son app Nuxt en temps réel avec Supabase Realtime.
Also available in English : Real-time Nuxt App updates made easy with Supabase
Découvrez comment mettre à jour l'UI de votre app Nuxt 3 en temps réel lors d'un update en base de données grâce à Supabase Realtime.
En 2020, j'ai créé mon premier side project : Compar'or avec Nuxt 2, Express pour l'API et MongoDB Atlas pour la DB.
Le but du projet était de créer un site permettant de comparer le prix des pièces d'or des différents sites de vente français.
Grâce à un cronjob, un script de webscraping (Puppeteer 👀) se lançait toutes les 5 minutes pour récupérer le prix des pièces d'or et mettre à jour la database.
Objectif
Dans cet article, je vais partager avec vous comment j'ai amélioré l'expérience utilisateur de mon app grâce à Supabase Realtime.
Problème : l'utilisateur doit recharger la page toutes les 5 minutes pour récupérer les données de prix à jour.
Solution : Créer un composant qui permet d'écouter les changements de notre DB PostgreSQL grâce à Supabase Realtime (via WebSockets). Chaque fois que le prix est mis à jour, nous affichons une animation en temps réel qui montre que le prix a augmenté ou diminué .
Bénéfices :
- Capter et diriger l'attention de l'utilisateur
- Souligner les informations importantes
- Suggérer un flux naturel
- Contribue à créer une image de marque plus professionnelle
Prérequis
Pour suivre cet article, vous devrez installer :
- Node.js
- Un éditeur de code | VSCode
- Extension VSCode : Volar
Création de notre projet Supabase
Avant de commencer à développer la feature, nous allons créer la base de données et notre API grâce à Supabase ✨
- Aller sur app.supabase.com.
- Inscrivez-vous avec votre compte GitHub. Ensuite, cliquez sur New Project et suivez les instructions :
- Ensuite cliquez sur Table editor puis créez une table en cochant les cases Enable RLS et Enable Realtime comme suit :
- Insèrez les données suivantes dans la table :
Comprendre l'option "Row-Level-Security" de PostgreSQL
Avec Supabase, nous pouvons accéder à nos données directement depuis le client (le navigateur). Le client a besoin d'un accès à la DB pour pouvoir interagir avec nos données et c'est pour cela que nous lui passerons, dans l'étape suivante, notre Supabase URL
et notre Anon key
.
Cela soulève une question intéressante :
Si ma clé anon est dans le client, quelqu'un ne peut-il pas lire mon Javascript et voler ma clé ?
La réponse est oui. Il est donc indispensable d'activer l'option RLS
lorsqu'on crée une table.
D'ailleurs, Supabase nous indique bien "Restrict access to your table by enabling RLS and writing Postgres policies.
If RLS is not enabled, anyone with the anon key can modify and delete your data."
En utilisant les Row-Level-Security policies
de PostgreSQL, nous pouvons définir des règles sur les données auxquelles la clé anon
est autorisée à accéder.
Si le RLS
est activé, mais qu'il n'y a aucune règle définie, la clé anon
ne donne pas accès aux données.
Dans notre projet, nous allons setup une nouvelle règle qui autorise la clé anon
à accéder aux données (read only) de la table coins
, comme suit :
Création de notre projet Nuxt 3
Ouvrez un terminal (si vous utilisez Visual Studio Code, vous pouvez ouvrir un terminal intégré) et utilisez la commande suivante pour créer un nouveau projet Nuxt 3 :
npx nuxi init <project-name>
Après avoir setup votre app, installez le package sass
grâce à cette commande :
yarn add -D sass
1. Add @nuxtjs/supabase
Nous utiliserons le module @nuxtjs/supabase crée par la communauté Nuxt pour avoir la meilleure Developer Experience possible. Rien de plus simple comme installation, let's go to : Getting started with @nuxtjs/supabase
Une fois le module installé, direction la homepage de votre app sur Supabase pour récupérer votre Supabase URL
et votre Anon key
:
Ensuite, créer un fichier .env
à la racine de votre projet et y ajouter les clés récupérées sur Supabase :
2. Add @nuxtjs/tailwindcss
Ce framework CSS n'est plus à présenter, il nous permettra d'ajouter rapidement du style à notre app. Pour l'installer, suivez les instructions de la doc officielle : Getting started with @nuxtjs/tailwindcss.
3. Add @heroicons/vue
Nous allons également utiliser Heroicons. Pour installer ce package d'icônes :
yarn add @heroicons/vue
Ensuite ajoutez ces lignes de configuration dans votre fichier nuxt.config.ts
:
Si ce n'est pas déjà fait, lancez votre app avec la commande yarn dev
, npm run dev
ou pnpm run dev
(selon le package manager node que vous avez choisi lors de l'installation de Nuxt) et vérifiez que tout fonctionne bien.
Création de la structure de notre app
- Créer les dossiers
public
,components
etpages
à la racine de votre projet. - Créer un fichier
index.vue
dans le dossierpages
. - Créer les fichiers
CoinCard.vue
,CoinCardUpIcon.vue
etCoinCardDownIcon.vue
dans le dossiercomponents
. - Créer un fichier
types.ts
à la racine du projet et y ajouter le typeCoin
:
- Importer 2 images de pièces dans le dossier
public
. Vous pouvez utiliser celles-ci :
Attention, les images doivent avoir le même nom que les valeurs de la colonne
img
de votre tablecoins
sur Supabase. En effet, nous avons utilisé le path/20_marianne.png
et/20_vreneli.png
. Les images doivent donc se nommer20_marianne.png
et20_vreneli.png
et être dans le dossierpublic
de notre projet.
La structure de votre projet devrait ressembler à cela :
Création de la page d'accueil
Dans notre fichier app.vue
, nous allons remplacer le composant <NuxtWelcome />
par le composant <NuxtPage />
:
Le composant <NuxtPage />
est nécessaire pour afficher les pages de premier niveau ou imbriquées situées dans le répertoire /pages
.
Ainsi, la homepage de notre app sera /pages/index.vue
.
Dans la balise <script>
de notre fichier index.vue
, nous allons :
- Importer les déclarations de types pour faciliter notre développement avec TypeScript.
- Initialiser notre client Supabase afin d'interagir avec notre DB.
- Récupérer toutes les pièces que contient notre table "coins" et affecter le résultat de la requête à notre tableau
coins
. - Une fois que le composant est monté, on s'abonne à la table "coins" de notre DB pour être notifié en temps réel des changements lors d'un "UPDATE".
payload
est un objet qui contient les données de la pièce updated. Nous trouverons l'index de la pièce à update dans notre tableaucoins
en comparant l'id de la pièce updated avec l'id de chaque pièce de notre tableau à l'aide de la méthode findIndex.- Création d'une condition qui check si l'ancien prix est différent du nouveau. Si oui, alors on appelle la fonction
onChangePrice
. - Cette fonction prend en paramètre l'index de la pièce à update et l'objet
newCoin
. - On compare l'ancien prix et le nouveau prix de la pièce pour déterminer quel symbole, et quelle classe CSS attribuer à la pièce qui vient d'être updated en plus de modifier son prix.
- Après 3s, on réinitialise les propriétés
change
etcolor
de la pièce pour qu'elle revienne à son rendu initial. - On oublie pas de désabonner le client Supabase lorsque le composant est unMounted (quand l'utilisateur quitte la page) afin d'éviter les fuites de mémoire 😉.
La majeure partie de notre logique est écrite. Il ne nous reste plus qu'à créer notre composant
<CoinCard />
qui sera réutilisé pour chaque pièce de notre tableaucoins
. Sans oublier nos composants<CoinCardUpIcon />
et<CoinCardDownIcon />
qui seront importés dynamiquement dans notre composant<CoinCard />
.
Créons d'abord les composants <CoinCardUpIcon />
et <CoinCardDownIcon />
:
Maintenant, créons notre composant <CoinCard />
. Ce composant récupérera la pièce de notre tableau coins
qu'on lui passera en props
dans notre composant parent index.vue
.
Le style de notre composant <CoinCard />
(à mettre dans la balise <style>
de notre composant) :
Enfin, nous pouvons retourner sur notre page index.vue
et importer notre composant <CoinCard />
dans la balise <template>
:
Résultat
Libre à vous d'incorporer cette feature dans votre prochain side-project. Que ce soit lors d'un update de prix, d'un ajout de produit ou d'une suppression, vous pouvez être sûr que vos utilisateurs apprécieront cette fonctionnalité 🚀
Live example : https://nuxt3-demo-supabase-realtime.vercel.app
Code source : Github