Frappez le sol avec Vue.js et Firestore

Publié: 2022-03-10
Résumé rapide ↬ Construire un MVP consiste à créer de nombreuses fonctionnalités en peu de temps. Vue.js est une bonne option, avec un minimum de passe-partout architectural et beaucoup de puissance brute. Tout ce dont il a besoin, c'est d'un endroit où stocker les données.

Google Firebase propose une nouvelle possibilité de stockage de données appelée "Firestore" (actuellement en phase bêta) qui s'appuie sur le succès de la base de données en temps réel Firebase , mais ajoute quelques fonctionnalités intéressantes. Dans cet article, nous allons configurer les bases d'une application Web à l'aide de Vue.js et Firestore.

Disons que vous avez cette idée géniale pour un nouveau produit (par exemple le prochain Twitter, Facebook ou Instagram, parce qu'on ne peut jamais avoir trop de social, n'est-ce pas ?). Pour commencer, vous souhaitez créer un prototype ou un produit minimum viable ( MVP ) de ce produit. L'objectif est de créer le cœur de l'application le plus rapidement possible afin que vous puissiez le montrer aux utilisateurs, obtenir des commentaires et analyser l'utilisation. L'accent est fortement mis sur la vitesse de développement et l'itération rapide.

Mais avant de commencer à construire, notre incroyable produit a besoin d'un nom. Appelons-le "Amazeballs". Ça va être legen — attendez-le — dary !

Voici une photo de comment je l'envisage:

Capture d'écran de l'application Amazeballs
L'application légendaire Amazeballs

Notre application Amazeballs est - bien sûr - tout au sujet du partage de friandises ringardes de votre vie personnelle avec des amis, dans ce qu'on appelle Balls. En haut se trouve un formulaire pour publier des balles, en dessous se trouvent les balles de vos amis.

Lors de la création d'un MVP, vous aurez besoin d'outils qui vous donnent le pouvoir d'implémenter rapidement les fonctionnalités clés ainsi que la flexibilité d'ajouter et de modifier rapidement des fonctionnalités ultérieurement. Mon choix se porte sur Vue.js car il s'agit d'un framework de rendu Javascript, soutenu par la suite Firebase (de Google) et sa nouvelle base de données en temps réel appelée Firestore.

Plus après saut! Continuez à lire ci-dessous ↓

Firestore est directement accessible à l'aide de méthodes HTTP normales, ce qui en fait une solution backend complète en tant que service dans laquelle vous n'avez pas à gérer l'un de vos propres serveurs, mais stockez toujours des données en ligne.

Cela semble puissant et intimidant, mais pas de soucis, je vais vous guider à travers les étapes de création et d'hébergement de cette nouvelle application Web. Remarquez la taille de la barre de défilement sur cette page ; il n'y a pas beaucoup d'étapes à franchir. De plus, si vous voulez savoir où placer chacun des extraits de code dans un référentiel de code, vous pouvez voir une version entièrement opérationnelle d'Amazeballs sur github.

Commençons

Nous commençons avec Vue.js. C'est idéal pour les débutants en Javascript, car vous commencez avec HTML et y ajoutez progressivement de la logique. Mais ne sous-estimez pas; il contient de nombreuses fonctionnalités puissantes. Cette combinaison en fait mon premier choix pour un framework frontal.

Vue.js dispose d'une interface de ligne de commande (CLI) pour les projets d'échafaudage. Nous allons l'utiliser pour obtenir rapidement la configuration de base. Commencez par installer la CLI, puis utilisez-la pour créer un nouveau projet basé sur le modèle "webpack-simple".

 npm install -g vue-cli vue init webpack-simple amazeballs

Si vous suivez les étapes à l'écran ( npm install et npm run dev ), un navigateur s'ouvrira avec un grand logo Vue.js.

Félicitations! C'était facile.

Ensuite, nous devons créer un projet Firebase. Rendez-vous sur https://console.firebase.google.com/ et créez un projet. Un projet démarre dans le plan Spark gratuit, qui vous donne une base de données limitée (1 Go de données, 50 000 lectures par jour) et 1 Go d'hébergement. C'est plus que suffisant pour notre MVP, et facilement évolutif lorsque l'application gagne du terrain.

Cliquez sur "Ajouter Firebase à votre application Web" pour afficher la configuration dont vous avez besoin. Nous utiliserons cette configuration dans notre application, mais d'une manière agréable Vue.js en utilisant l'état partagé.

Commencez npm install firebase , puis créez un fichier appelé src/store.js . C'est à cet endroit que nous allons placer l'état partagé afin que chaque composant Vue.js puisse y accéder indépendamment de l'arborescence des composants. Ci-dessous le contenu du fichier. L'état ne contient que quelques espaces réservés pour le moment.

 import Vue from 'vue'; import firebase from 'firebase/app'; import 'firebase/firestore'; // Initialize Firebase, copy this from the cloud console // Or use mine :) var config = { apiKey: "AIzaSyDlRxHKYbuCOW25uCEN2mnAAgnholag8tU", authDomain: "amazeballs-by-q42.firebaseapp.com", databaseURL: "https://amazeballs-by-q42.firebaseio.com", projectId: "amazeballs-by-q42", storageBucket: "amazeballs-by-q42.appspot.com", messagingSenderId: "972553621573" }; firebase.initializeApp(config); // The shared state object that any vue component can get access to. // Has some placeholders that we'll use further on! export const store = { ballsInFeed: null, currentUser: null, writeBall: (message) => console.log(message) };

Nous allons maintenant ajouter les composants Firebase. Un morceau de code pour obtenir les données du Firestore :

 // a reference to the Balls collection const ballsCollection = firebase.firestore() .collection('balls'); // onSnapshot is executed every time the data // in the underlying firestore collection changes // It will get passed an array of references to // the documents that match your query ballsCollection .onSnapshot((ballsRef) => { const balls = []; ballsRef.forEach((doc) => { const ball = doc.data(); ball.id = doc.id; balls.push(ball); }); store.ballsInFeed = balls; });

Et puis remplacez la fonction writeBall par une autre qui exécute réellement une écriture :

 writeBall: (message) => ballsCollection.add({ createdOn: new Date(), author: store.currentUser, message })

Remarquez comment les deux sont complètement découplés. Lorsque vous insérez dans une collection, onSnapshot est déclenché car vous avez inséré un élément. Cela rend la gestion de l'état beaucoup plus facile.

Vous avez maintenant un objet d'état partagé auquel n'importe quel composant Vue.js peut facilement accéder. Faisons-en bon usage.

Postez des trucs !

Tout d'abord, découvrons qui est l'utilisateur actuel.

Firebase dispose d'API d'authentification qui vous aident à faire connaissance avec votre utilisateur. Activez les options appropriées sur la console Firebase dans AuthentificationMéthode de connexion . Pour l'instant, je vais utiliser Google Login - avec un bouton très simple.

Capture d'écran de la page de connexion avec authentification Google
Authentification avec Google Login

Firebase ne vous donne aucune aide sur l'interface, vous devrez donc créer vos propres boutons "Connexion avec Google/Facebook/Twitter" et/ou champs de saisie de nom d'utilisateur/mot de passe. Votre composant de connexion ressemblera probablement un peu à ceci :

 <template> <div> <button @click.prevent="signInWithGoogle">Log in with Google</button> </div> </template> <script> import firebase from 'firebase/app'; import 'firebase/auth'; export default { methods: { signInWithGoogle() { var provider = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithPopup(provider); } } } </script>

Maintenant, il y a une autre pièce du puzzle de connexion, et c'est l'obtention de la variable currentUser dans le magasin. Ajoutez ces lignes à votre store.js :

 // When a user logs in or out, save that in the store firebase.auth().onAuthStateChanged((user) => { store.currentUser = user; });

En raison de ces trois lignes, chaque fois que l'utilisateur actuellement connecté change (se connecte ou se déconnecte), store.currentUser change également. Postons quelques balles !

Capture d'écran de l'option de déconnexion
L'état de connexion est stocké dans le fichier store.js

Le formulaire de saisie est un composant Vue.js séparé qui est relié à la fonction writeBall dans notre magasin, comme ceci :

 <template> <form @submit.prevent="formPost"> <textarea v-model="message" /> <input type="submit" value="DUNK!" /> </form> </template> <script> import { store } from './store'; export default { data() { return { message: null, }; }, methods: { formPost() { store.writeBall(this.message); } }, } </script>

Impressionnant! Désormais, les gens peuvent se connecter et commencer à publier des balles. Mais attendez, il nous manque l'autorisation. Nous voulons que vous ne puissiez publier des balles que vous-même, et c'est là que les règles de Firestore entrent en jeu. Elles sont constituées d'un code Javascript qui définit les privilèges d'accès à la base de données. Vous pouvez les saisir via la console Firestore, mais vous pouvez également utiliser la CLI Firebase pour les installer à partir d'un fichier sur le disque. Installez-le et exécutez-le comme ceci :

 npm install -g firebase-tools firebase login firebase init firestore

Vous obtiendrez un fichier nommé firestore.rules dans lequel vous pourrez ajouter une autorisation pour votre application. Nous voulons que chaque utilisateur puisse insérer ses propres balles, mais pas insérer ou modifier celles de quelqu'un d'autre. L'exemple ci-dessous fonctionne bien. Il permet à tout le monde de lire tous les documents de la base de données, mais vous ne pouvez insérer que si vous êtes connecté, et la ressource insérée a un champ "auteur" qui est le même que l'utilisateur actuellement connecté.

 service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read: if true; allow create: if request.auth.uid != null && request.auth.uid == request.resource.data.author; } } }

Il ressemble à quelques lignes de code, mais il est très puissant et peut devenir complexe très rapidement. Firebase travaille sur un meilleur outillage autour de cette partie, mais pour l'instant, il s'agit d'essais et d'erreurs jusqu'à ce qu'il se comporte comme vous le souhaitez.

Si vous exécutez firebase deploy , les règles Firestore seront déployées et sécuriseront vos données de production en quelques secondes.

Ajout de la logique du serveur

Sur votre page d'accueil, vous souhaitez voir une chronologie avec les balles de vos amis. Selon la manière dont vous souhaitez déterminer quelles balles un utilisateur voit, l'exécution de cette requête directement sur la base de données peut constituer un goulot d'étranglement pour les performances. Une alternative consiste à créer une fonction Firebase Cloud qui s'active sur chaque balle publiée et l'ajoute aux murs de tous les amis de l'auteur. De cette façon, c'est asynchrone, non bloquant et éventuellement cohérent. Ou en d'autres termes, il y arrivera.

Pour que les exemples restent simples, je vais faire une petite démo en écoutant les balles créées et en modifiant leur message. Non pas parce que c'est particulièrement utile, mais pour vous montrer à quel point il est facile de mettre en place des fonctions cloud.

 const functions = require('firebase-functions'); exports.createBall = functions.firestore .document('balls/{ballId}') .onCreate(event => { var createdMessage = event.data.get('message'); return event.data.ref.set({ message: createdMessage + ', yo!' }, {merge: true}); });

Oh, attendez, j'ai oublié de vous dire où écrire ce code.

 firebase init functions

Cela crée le répertoire des fonctions avec un index.js . C'est le fichier dans lequel vous pouvez écrire vos propres fonctions Cloud . Ou copier-coller le mien si vous êtes très impressionné.

Cloud Functions vous offre un endroit idéal pour dissocier différentes parties de votre application et les faire communiquer de manière asynchrone. Ou, dans le style de dessin architectural :

Schéma architectural de la logique de serveur de Cloud Functions
Communication asynchrone entre les différents composants de votre application

Dernière étape : Déploiement

Firebase a son option d'hébergement disponible pour cela, et vous pouvez l'utiliser via la CLI Firebase.

 firebase init hosting

Choisissez dist comme répertoire public, puis "Oui" pour réécrire toutes les URL dans index.html . Cette dernière option vous permet d'utiliser vue-router pour gérer de jolies URL au sein de votre application.

Il y a maintenant un petit obstacle : le dossier dist ne contient pas de fichier index.html qui pointe vers la bonne version de votre code. Pour résoudre ce problème, ajoutez un script npm à votre package.json :

 { "scripts": { "deploy": "npm run build && mkdir dist/dist && mv dist/*.* dist/dist/ && cp index.html dist/ && firebase deploy" } }

Maintenant, exécutez simplement npm deploy et la CLI Firebase vous montrera l'URL de votre code hébergé !

Quand utiliser cette architecture

Cette configuration est parfaite pour un MVP. À la troisième fois, vous aurez une application Web fonctionnelle en quelques minutes, soutenue par une base de données évolutive hébergée gratuitement. Vous pouvez immédiatement commencer à créer des fonctionnalités.

De plus, il y a beaucoup d'espace pour grandir. Si Cloud Functions n'est pas assez puissant, vous pouvez par exemple recourir à une API traditionnelle exécutée sur docker dans Google Cloud. En outre, vous pouvez mettre à niveau votre architecture Vue.js avec vue-router et vuex et utiliser la puissance de webpack inclus dans le modèle vue-cli.

Ce ne sont pas tous des arcs-en-ciel et des licornes, cependant. La mise en garde la plus notoire est le fait que vos clients parlent immédiatement à votre base de données. Il n'y a pas de couche middleware que vous pouvez utiliser pour transformer les données brutes dans un format plus simple pour le client. Donc, vous devez le stocker d'une manière conviviale pour le client. Chaque fois que vos clients demandent un changement, vous aurez du mal à exécuter des migrations de données sur Firebase. Pour cela, vous devrez écrire un client Firestore personnalisé qui lit chaque enregistrement, le transforme et le réécrit.

Prenez le temps de décider de votre modèle de données. Si vous devez modifier votre modèle de données ultérieurement, la migration des données est votre seule option.

"

Alors, quels sont les exemples de projets utilisant ces outils ? Parmi les grands noms qui utilisent Vue.js figurent Laravel, GitLab et (pour les Néerlandais) nu.nl. Firestore est toujours en version bêta, donc pas encore beaucoup d'utilisateurs actifs, mais la suite Firebase est déjà utilisée par National Public Radio , Shazam et d'autres. J'ai vu des collègues implémenter Firebase pour le jeu Road Warriors basé sur Unity qui a été téléchargé plus d'un million de fois au cours des cinq premiers jours. Cela peut prendre une certaine charge et il est très polyvalent avec des clients pour le Web, le mobile natif, Unity, etc.

Où puis-je m'inscrire ? !

Si vous souhaitez en savoir plus, considérez les ressources suivantes :

  • Exemple de travail contenant tout le code ci-dessus
  • Documentation sur Vue.js, vue-router, vue-cli
  • Documentation sur Firebase
  • Une façon amusante de mieux connaître Firebase - leur blog YouTube

Bon codage !