Uderz w ziemię z Vue.js i Firestore

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ Budowanie MVP polega na zbudowaniu dużej ilości funkcjonalności w krótkim czasie. Vue.js to dobra opcja, z minimalną ilością schematu architektonicznego i dużą ilością surowej mocy. Wszystko czego potrzebuje to miejsce do przechowywania danych.

Google Firebase ma nową możliwość przechowywania danych o nazwie „Firestore” (obecnie w fazie beta), która opiera się na sukcesie bazy danych czasu rzeczywistego Firebase , ale dodaje kilka ciekawych funkcji. W tym artykule skonfigurujemy podstawy aplikacji internetowej przy użyciu Vue.js i Firestore.

Załóżmy, że masz świetny pomysł na nowy produkt (np. następny Twitter, Facebook czy Instagram, bo nigdy nie możemy mieć za dużo mediów społecznościowych, prawda?). Na początek chcesz stworzyć prototyp lub produkt o minimalnej żywotności ( MVP ) tego produktu. Celem jest jak najszybsze zbudowanie rdzenia aplikacji, aby można było pokazać go użytkownikom, uzyskać opinie i przeanalizować użycie. Nacisk kładziony jest na szybkość rozwoju i szybkie iteracje.

Ale zanim zaczniemy budować, nasz niesamowity produkt potrzebuje nazwy. Nazwijmy to „Amazeballs”. To będzie legenda — poczekaj na to — dary !

Oto ujęcie, jak to sobie wyobrażam:

Zrzut ekranu aplikacji Amazeballs
Legendarna aplikacja Amazeballs

Nasza aplikacja Amazeballs to – oczywiście – dzielenie się tandetnymi smakołykami z twojego życia osobistego z przyjaciółmi, w tak zwanych piłkach. Na górze znajduje się formularz do wysyłania kulek, poniżej są kulki twoich znajomych.

Tworząc MVP, będziesz potrzebować narzędzi, które dadzą Ci możliwość szybkiego wdrożenia kluczowych funkcji, a także elastyczność w szybkim dodawaniu i zmienianiu funkcji później. Mój wybór pada na Vue.js, ponieważ jest to framework renderujący JavaScript, wspierany przez pakiet Firebase (przez Google) i nową bazę danych czasu rzeczywistego o nazwie Firestore.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Dostęp do Firestore można uzyskać bezpośrednio przy użyciu normalnych metod HTTP, co sprawia, że ​​jest to pełne rozwiązanie typu backend-as-a-service, w którym nie musisz zarządzać żadnymi własnymi serwerami, ale nadal przechowujesz dane online.

Brzmi potężnie i zniechęcająco, ale bez potu, przeprowadzę Cię przez etapy tworzenia i hostowania tej nowej aplikacji internetowej. Zwróć uwagę, jak duży jest pasek przewijania na tej stronie; nie ma do tego dużej ilości kroków. Ponadto, jeśli chcesz wiedzieć, gdzie umieścić każdy z fragmentów kodu w repozytorium kodu, możesz zobaczyć w pełni działającą wersję Amazeballs na github.

Zaczynajmy

Zaczynamy od Vue.js. Jest świetny dla początkujących JavaScript, ponieważ zaczynasz od HTML i stopniowo dodajesz do niego logikę. Ale nie lekceważ; zawiera wiele zaawansowanych funkcji. Ta kombinacja sprawia, że ​​jest to mój pierwszy wybór dla frameworka front-end.

Vue.js posiada interfejs wiersza poleceń (CLI) dla projektów rusztowań. Wykorzystamy to, aby szybko ustawić gołe kości. Najpierw zainstaluj CLI, a następnie użyj go do stworzenia nowego projektu na podstawie szablonu „webpack-simple”.

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

Jeśli postępujesz zgodnie z instrukcjami na ekranie ( npm install i npm run dev ) otworzy się przeglądarka z dużym logo Vue.js.

Gratulacje! To było łatwe.

Następnie musimy utworzyć projekt Firebase. Wejdź na https://console.firebase.google.com/ i utwórz projekt. Projekt rozpoczyna się w bezpłatnym abonamencie Spark, który zapewnia ograniczoną bazę danych (1 GB danych, 50 000 odczytów dziennie) i 1 GB hostingu. To jest więcej niż wystarczające dla naszego MVP i można je łatwo zaktualizować, gdy aplikacja zyskuje na popularności.

Kliknij „Dodaj Firebase do swojej aplikacji internetowej”, aby wyświetlić potrzebną konfigurację. Użyjemy tego configu w naszej aplikacji, ale w miły sposób Vue.js, używając stanu współdzielonego.

Najpierw npm install firebase , a następnie utwórz plik o nazwie src/store.js . To jest miejsce, w którym zamierzamy umieścić stan współdzielony, aby każdy komponent Vue.js mógł uzyskać do niego dostęp niezależnie od drzewa komponentów. Poniżej znajduje się zawartość pliku. Na razie stan zawiera tylko niektóre symbole zastępcze.

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

Teraz dodamy części Firebase. Jeden fragment kodu, aby pobrać dane z 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; });

A następnie zamień funkcję writeBall na taką, która faktycznie wykonuje zapis:

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

Zwróć uwagę, jak te dwie rzeczy są całkowicie oddzielone. Kiedy wstawiasz do kolekcji, onSnapshot jest wyzwalany, ponieważ wstawiłeś element. To znacznie ułatwia zarządzanie państwem.

Teraz masz udostępniony obiekt stanu, do którego każdy komponent Vue.js może łatwo uzyskać dostęp. Wykorzystajmy to dobrze.

Opublikuj rzeczy!

Najpierw dowiedzmy się, kim jest obecny użytkownik.

Firebase posiada interfejsy API uwierzytelniania, które pomagają w trudach poznania użytkownika. Włącz odpowiednie w Konsoli Firebase w UwierzytelnianieMetoda logowania . Na razie zamierzam używać Google Login — z bardzo mało wyszukanym przyciskiem.

Zrzut ekranu strony logowania z uwierzytelnianiem Google
Uwierzytelnianie za pomocą logowania Google

Firebase nie zapewnia żadnej pomocy dotyczącej interfejsu, więc musisz utworzyć własne przyciski „Zaloguj się przez Google/Facebook/Twitter” i/lub pola wprowadzania nazwy użytkownika/hasła. Twój komponent logowania prawdopodobnie będzie wyglądał mniej więcej tak:

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

Teraz jest jeszcze jeden element układanki logowania, a jest nim pobranie zmiennej currentUser w sklepie. Dodaj te wiersze do swojego store.js :

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

Dzięki tym trzem wierszom za każdym razem, gdy zmienia się aktualnie zalogowany użytkownik (loguje się lub wylogowuje), zmienia się również store.currentUser . Opublikujmy kilka kulek!

Zrzut ekranu opcji wylogowania
Stan logowania jest przechowywany w pliku store.js

Formularz wejściowy to osobny komponent Vue.js, który jest podłączony do funkcji writeBall w naszym sklepie, tak jak to:

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

Świetny! Teraz ludzie mogą się zalogować i zacząć publikować piłki. Ale czekaj, brakuje nam autoryzacji. Chcemy, abyś mógł publikować kulki tylko sam, i tu właśnie wkraczają reguły Firestore . Składają się one z kodu JavaScript, który definiuje uprawnienia dostępu do bazy danych. Możesz wprowadzić je za pomocą konsoli Firestore, ale możesz również użyć Firebase CLI, aby zainstalować je z pliku na dysku. Zainstaluj i uruchom go w ten sposób:

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

Otrzymasz plik o nazwie firestore.rules , w którym możesz dodać autoryzację dla swojej aplikacji. Chcemy, aby każdy użytkownik mógł wstawiać własne kulki, ale nie wstawiać ani edytować cudzych. Poniższy przykład robi ładnie. Pozwala każdemu na odczytanie wszystkich dokumentów w bazie danych, ale możesz je wstawiać tylko wtedy, gdy jesteś zalogowany, a wstawiony zasób ma pole „autor”, które jest takie samo jak aktualnie zalogowany użytkownik.

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

Wygląda na zaledwie kilka linijek kodu, ale jest bardzo potężny i może bardzo szybko się skomplikować. Firebase pracuje nad lepszymi narzędziami wokół tej części, ale na razie jest to metoda prób i błędów, dopóki nie będzie działać tak, jak chcesz.

Jeśli uruchomisz firebase deploy , reguły Firestore zostaną wdrożone i zabezpieczą Twoje dane produkcyjne w ciągu kilku sekund.

Dodawanie logiki serwera

Na swojej stronie głównej chcesz zobaczyć oś czasu z piłkami znajomych. W zależności od tego, jak chcesz określić, które kulki widzi użytkownik, wykonanie tego zapytania bezpośrednio w bazie danych może być wąskim gardłem wydajności. Alternatywą jest stworzenie funkcji Firebase Cloud , która aktywuje się na każdym opublikowanym Ballu i dołącza ją do ścian wszystkich znajomych autora. W ten sposób jest asynchroniczny, nieblokujący i ostatecznie spójny. Innymi słowy, dotrze tam.

Aby przykłady były proste, zrobię małe demo słuchania stworzonych Kulek i modyfikowania ich przekazu. Nie dlatego, że jest to szczególnie przydatne, ale aby pokazać, jak łatwo jest uruchomić funkcje chmury.

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

Och, czekaj, zapomniałem ci powiedzieć, gdzie napisać ten kod.

 firebase init functions

Tworzy to katalog funkcji z index.js . To plik, w którym możesz zapisać własne funkcje Cloud Functions . Lub skopiuj i wklej mój, jeśli jesteś pod wrażeniem.

Cloud Functions to dobre miejsce do oddzielenia różnych części aplikacji i asynchronicznej komunikacji. Lub w architektonicznym stylu rysunku:

Schemat architektury logiki serwera Cloud Functions
Asynchroniczna komunikacja między różnymi komponentami Twojej aplikacji

Ostatni krok: wdrożenie

Firebase ma do tego dostępną opcję Hostingu, z której możesz korzystać za pośrednictwem interfejsu wiersza polecenia Firebase.

 firebase init hosting

Wybierz dist jako katalog publiczny, a następnie „Tak”, aby przepisać wszystkie adresy URL do index.html . Ta ostatnia opcja pozwala używać vue-router do zarządzania ładnymi adresami URL w Twojej aplikacji.

Teraz jest mała przeszkoda: folder dist nie zawiera pliku index.html , który wskazuje właściwą kompilację kodu. Aby to naprawić, dodaj skrypt npm do swojego package.json :

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

Teraz po prostu uruchom npm deploy , a Firebase CLI pokaże Ci adres URL hostowanego kodu!

Kiedy używać tej architektury?

Ta konfiguracja jest idealna dla MVP. Za trzecim razem będziesz mieć działającą aplikację internetową w ciągu kilku minut — wspieraną przez skalowalną bazę danych, która jest hostowana bezpłatnie. Możesz natychmiast rozpocząć tworzenie funkcji.

Poza tym jest dużo miejsca na rozwój. Jeśli funkcje Cloud Functions nie są wystarczająco wydajne, możesz wrócić do tradycyjnego interfejsu API działającego na przykład w Docker w Google Cloud. Możesz także uaktualnić swoją architekturę Vue.js za pomocą vue-router i vuex oraz wykorzystać moc pakietu webpack zawartego w szablonie vue-cli.

Jednak to nie wszystkie tęcze i jednorożce. Najbardziej znanym zastrzeżeniem jest fakt, że Twoi klienci natychmiast rozmawiają z Twoją bazą danych. Nie ma warstwy oprogramowania pośredniczącego, której można użyć do przekształcenia nieprzetworzonych danych do formatu łatwiejszego dla klienta. Musisz więc przechowywać go w sposób przyjazny dla klienta. Za każdym razem, gdy Twoi klienci zażądają zmiany, uruchomienie migracji danych w Firebase będzie dość trudne. W tym celu musisz napisać niestandardowego klienta Firestore, który odczytuje każdy rekord, przekształca go i zapisuje z powrotem.

Poświęć trochę czasu na podjęcie decyzji o modelu danych. Jeśli musisz później zmienić model danych, migracja danych jest jedyną opcją.

Jakie są zatem przykłady projektów wykorzystujących te narzędzia? Wśród wielkich nazwisk, które używają Vue.js, są Laravel, GitLab i (dla Holendrów) nu.nl. Firestore jest nadal w fazie beta, więc nie ma jeszcze wielu aktywnych użytkowników, ale pakiet Firebase jest już używany przez National Public Radio , Shazam i inne. Widziałem, jak koledzy wdrażają Firebase w opartej na Unity grze Road Warriors, która została pobrana ponad milion razy w ciągu pierwszych pięciu dni. Może zająć sporo czasu i jest bardzo wszechstronny w przypadku klientów internetowych, natywnych urządzeń mobilnych, Unity i tak dalej.

Gdzie mam się zarejestrować?!

Jeśli chcesz dowiedzieć się więcej, rozważ następujące zasoby:

  • Próbka robocza zawierająca cały powyższy kod
  • Dokumentacja dotycząca Vue.js, vue-router, vue-cli
  • Dokumentacja dotycząca Firebase
  • Zabawny sposób na lepsze poznanie Firebase — ich blog na YouTube

Udanego kodowania!