Pierwsze kroki: pisanie, testowanie i wdrażanie pierwszych funkcji


Aby rozpocząć korzystanie z Cloud Functions, zapoznaj się z tym samouczkiem. Zaczyna się on od wymaganych zadań konfiguracyjnych, a następnie pokazuje, jak tworzyć, testować i wdrażać 2 powiązane funkcje:

  • Funkcja „add message” (dodaj wiadomość), która udostępnia adres URL akceptujący wartość tekstową i zapisujący ją w Cloud Firestore.
  • Funkcja „zapisz wielkimi literami”, która jest aktywowana przez Cloud Firestore zapis i przekształca tekst na wielkie litery.

Oto pełny przykładowy kod zawierający funkcje:

Node.jsPython
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

initializeApp();

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await getFirestore()
      .collection("messages")
      .add({original: original});
  // Send back a message that we've successfully written the message
  res.json({result: `Message with ID: ${writeResult.id} added.`});
});

// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

  // Access the parameter `{documentId}` with `event.params`
  logger.log("Uppercasing", event.params.documentId, original);

  const uppercase = original.toUpperCase();

  // You must return a Promise when performing
  // asynchronous tasks inside a function
  // such as writing to Firestore.
  // Setting an 'uppercase' field in Firestore document returns a Promise.
  return event.data.ref.set({uppercase}, {merge: true});
});
# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()


@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")


@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

Informacje o tym samouczku

W tym przykładzie wybraliśmy Cloud Firestore i funkcje aktywowane przez HTTP, ponieważ te aktywatory w tle można dokładnie przetestować za pomocą Firebase Local Emulator Suite. Ten zestaw narzędzi obsługuje też aktywatory wywoływane Realtime Database, Cloud Storage, PubSub, Auth i HTTP. Inne rodzaje wyzwalaczy w tle, takie jak wyzwalacze Remote Config i TestLab, można testować interaktywnie za pomocą zestawów narzędzi, które nie są opisane na tej stronie.

W kolejnych sekcjach tego samouczka znajdziesz szczegółowe informacje o krokach wymaganych do skompilowania, przetestowania i wdrożenia próbki.

Tworzenie projektu Firebase

  1. W Firebasekonsoli kliknij Dodaj projekt.

    • Aby dodać zasoby Firebase do istniejącego Google Cloudprojektu, wpisz jego nazwę lub wybierz ją z menu.

    • Aby utworzyć nowy projekt, wpisz jego nazwę. Możesz też opcjonalnie edytować identyfikator projektu wyświetlany pod nazwą projektu.

  2. Jeśli pojawi się taka prośba, przeczytaj i zaakceptuj warunki usługi Firebase.

  3. Kliknij Dalej.

  4. (Opcjonalnie) skonfiguruj Google Analytics w projekcie, co umożliwi optymalne korzystanie z tych usług Firebase: Firebase A/B Testing, Cloud Messaging, Crashlytics, In-App MessagingRemote Config (w tym Personalizacja).

    Wybierz istniejące Google Analyticskonto lub utwórz nowe. Jeśli tworzysz nowe konto, wybierz Analyticslokalizację raportowania, a następnie zaakceptuj ustawienia udostępniania danych i Google Analytics warunki korzystania z usługi w przypadku projektu.

  5. Kliknij Utwórz projekt (lub Dodaj Firebase, jeśli dodajesz Firebase do istniejącego Google Cloud projektu).

Firebase automatycznie udostępnia zasoby dla Twojego projektu Firebase. Po zakończeniu procesu otworzy się strona podsumowania projektu Firebase w Firebasekonsoli.

Konfigurowanie środowiska i wiersza poleceń Firebase

Node.jsPython

Do pisania funkcji potrzebujesz środowiska Node.js, a do wdrażania funkcji w środowisku wykonawczym Cloud Functions potrzebujesz interfejsu Firebase CLI. Do instalacji Node.js i npm zalecany jest Node Version Manager.

Po zainstalowaniu Node.js i npm zainstaluj FirebaseCLI w wybrany przez siebie sposób. Aby zainstalować interfejs wiersza poleceń za pomocą npm, użyj tego polecenia:

npm install -g firebase-tools

Spowoduje to zainstalowanie polecenia firebase dostępnego globalnie. Jeśli polecenie się nie powiedzie, może być konieczna zmiana uprawnień npm. Aby zaktualizować firebase-tools do najnowszej wersji, ponownie uruchom to samo polecenie.

Aby pisać funkcje, musisz mieć środowisko Pythona, a do wdrażania funkcji w środowisku wykonawczym Cloud Functions potrzebujesz interfejsu Firebase CLI. Zalecamy używanie venv do izolowania zależności. Obsługiwane są wersje Pythona 3.10 i 3.11.

Po zainstalowaniu Pythona zainstaluj Firebaseinterfejs wiersza poleceń wybraną metodą.

Zainicjuj projekt

Gdy zainicjujesz Firebase SDK dla Cloud Functions, utworzysz pusty projekt zawierający zależności i minimalny przykładowy kod. Jeśli używasz Node.js, możesz wybrać język TypeScript lub JavaScript do tworzenia funkcji. Na potrzeby tego samouczka musisz też zainicjować Cloud Firestore.

Aby zainicjować projekt:

  1. Uruchom firebase login, aby zalogować się w przeglądarce i uwierzytelnić interfejs Firebase CLI.
  2. Przejdź do katalogu projektu Firebase.
  3. Uruchom firebase init firestore. W tym samouczku możesz zaakceptować wartości domyślne, gdy pojawi się prośba o podanie reguł Firestore i plików indeksu. Jeśli nie używasz jeszcze Cloud Firestore w tym projekcie, musisz też wybrać tryb początkowy i lokalizację Firestore zgodnie z opisem w artykule Wprowadzenie do Cloud Firestore.
  4. Uruchom firebase init functions. Interfejs CLI wyświetli prośbę o wybranie istniejącej bazy kodu lub zainicjowanie i nazwanie nowej. Na początek wystarczy jedna baza kodu w domyślnej lokalizacji. Później, gdy Twoje wdrożenie się rozwinie, możesz uporządkować funkcje w bazach kodu.
  5. Interfejs CLI oferuje te opcje obsługi języków:

    • JavaScript
    • TypeScript
    • Python

    Na potrzeby tego samouczka wybierz JavaScript lub Python. Informacje o tworzeniu funkcji w TypeScript znajdziesz w artykule Pisanie funkcji w TypeScript.

  6. Interfejs CLI umożliwia instalowanie zależności. Możesz odrzucić tę prośbę, jeśli chcesz zarządzać zależnościami w inny sposób.

Po pomyślnym wykonaniu tych poleceń struktura projektu będzie wyglądać tak:

Node.jsPython
myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
      |
      +- .eslintrc.json  # Optional file containing rules for JavaScript linting.
      |
      +- package.json  # npm package file describing your Cloud Functions code
      |
      +- index.js      # Main source file for your Cloud Functions code
      |
      +- node_modules/ # Directory where your dependencies (declared in
                        # package.json) are installed

W przypadku Node.js plik package.json utworzony podczas inicjowania zawiera ważny klucz: "engines": {"node": "18"}. Określa wersję Node.js do pisania i wdrażania funkcji. Możesz wybrać inne obsługiwane wersje.

myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
      |
      +- main.py      # Main source file for your Cloud Functions code
      |
      +- requirements.txt  #  List of the project's modules and packages 
      |
      +- venv/ # Directory where your dependencies are installed

Zaimportuj wymagane moduły i zainicjuj aplikację.

Po ukończeniu zadań konfiguracyjnych możesz otworzyć katalog źródłowy i zacząć dodawać kod zgodnie z opisem w dalszej części tego artykułu. W tym przykładzie projekt musi zaimportować moduły Cloud Functions i Admin SDK. Dodaj do pliku źródłowego wiersze podobne do tych:

Node.jsPython
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

initializeApp();
# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()

Te wiersze wczytują wymagane moduły i inicjują instancję aplikacji admin, w której można wprowadzać Cloud Firestore zmiany. Wszędzie tam, gdzie dostępny jest pakiet Admin SDK, czyli w przypadku FCM, AuthenticationFirebase Realtime Database, zapewnia on zaawansowany sposób integracji Firebase za pomocą Cloud Functions.

Firebase CLI automatycznie instaluje pakiet Firebase Admin SDK i Firebase pakiet SDK dla modułów Cloud Functions podczas inicjowania projektu. Więcej informacji o dodawaniu bibliotek innych firm do projektu znajdziesz w artykule Obsługa zależności.

Dodawanie funkcji „dodaj wiadomość”

W przypadku funkcji „add message” (dodaj wiadomość) dodaj do pliku źródłowego te wiersze:

Node.jsPython
// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await getFirestore()
      .collection("messages")
      .add({original: original});
  // Send back a message that we've successfully written the message
  res.json({result: `Message with ID: ${writeResult.id} added.`});
});
@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")

Funkcja „add message” (dodaj wiadomość) to punkt końcowy HTTP. Każde żądanie wysłane do punktu końcowego powoduje przekazanie obiektów żądania i odpowiedzi do modułu obsługi żądań na Twojej platformie (onRequest() lub on_request).

Funkcje HTTP są synchroniczne (podobnie jak funkcje wywoływane), więc należy jak najszybciej wysłać odpowiedź i odłożyć pracę za pomocą Cloud Firestore. Funkcja HTTP „add message” przekazuje wartość tekstową do punktu końcowego HTTP i wstawia ją do bazy danych pod ścieżką /messages/:documentId/original.

Dodawanie funkcji „zmień na wielkie litery”

W przypadku funkcji „make uppercase” dodaj do pliku źródłowego te wiersze:

Node.jsPython
// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

  // Access the parameter `{documentId}` with `event.params`
  logger.log("Uppercasing", event.params.documentId, original);

  const uppercase = original.toUpperCase();

  // You must return a Promise when performing
  // asynchronous tasks inside a function
  // such as writing to Firestore.
  // Setting an 'uppercase' field in Firestore document returns a Promise.
  return event.data.ref.set({uppercase}, {merge: true});
});
@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

Funkcja „make uppercase” (zmień na wielkie litery) jest wykonywana, gdy Cloud Firestore jest zapisywany w dokumencie, w którym ma być nasłuchiwana. Ze względu na wydajność podaj jak najdokładniejsze informacje.

Klamry – np. {documentId} – otaczają „parametry”, czyli symbole wieloznaczne, które w wywołaniu zwrotnym udostępniają dopasowane dane. Cloud Firestore wywołuje wywołanie zwrotne za każdym razem, gdy dodawane są nowe wiadomości.

W Node.js funkcje sterowane zdarzeniami, takie jak Cloud Firestore, są asynchroniczne. Funkcja wywołania zwrotnego powinna zwracać wartość null, obiekt lub obietnicę. Jeśli nie zwrócisz żadnych danych, funkcja przekroczy limit czasu, co będzie oznaczać błąd, i zostanie ponowiona. Zobacz Synchronizacja, asynchroniczność i obietnice.

Emulowanie wykonywania funkcji

Firebase Local Emulator Suite umożliwia tworzenie i testowanie aplikacji na komputerze lokalnym zamiast wdrażania ich w projekcie Firebase. Zdecydowanie zalecamy testowanie lokalne podczas programowania, ponieważ zmniejsza ono ryzyko wystąpienia błędów w kodzie, które mogą generować koszty w środowisku produkcyjnym (np. nieskończona pętla).

Aby emulować funkcje:

  1. Uruchom firebase emulators:start i sprawdź w danych wyjściowych adres URL Emulator Suite UI. Domyślnie jest to localhost:4000, ale może być hostowany na innym porcie na Twoim komputerze. Wpisz ten adres URL w przeglądarce, aby otworzyć Emulator Suite UI.

  2. Sprawdź dane wyjściowe polecenia firebase emulators:start, aby znaleźć adres URL funkcji HTTP. Będzie on wyglądać podobnie do http://localhost:5001/MY_PROJECT/us-central1/addMessage, z tą różnicą, że:

    1. MY_PROJECT zostanie zastąpiony identyfikatorem projektu.
    2. Port może się różnić na Twoim komputerze lokalnym.
  3. Dodaj ciąg zapytania ?text=uppercaseme na końcu adresu URL funkcji. Powinno to wyglądać mniej więcej tak:http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme. Opcjonalnie możesz zmienić wiadomość „uppercaseme” na wiadomość niestandardową.

  4. Utwórz nową wiadomość, otwierając adres URL w nowej karcie przeglądarki.

  5. Sprawdź efekty funkcji w Emulator Suite UI:

    1. Na karcie Logi powinny być widoczne nowe logi wskazujące, że funkcje HTTP zostały uruchomione:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. Na karcie Firestore powinien być widoczny dokument zawierający oryginalną wiadomość oraz jej wersję zapisaną wielkimi literami (jeśli oryginalna wiadomość to „uppercaseme”, zobaczysz „UPPERCASEME”).

Wdrażanie funkcji w środowisku produkcyjnym

Gdy funkcje będą działać w emulatorze zgodnie z oczekiwaniami, możesz je wdrożyć, przetestować i uruchomić w środowisku produkcyjnym. Pamiętaj, że aby wdrożyć projekt w środowisku produkcyjnym, musisz mieć abonament Blaze. Sprawdź Cloud Functions cennik.

Aby ukończyć samouczek, wdróż funkcje, a następnie je wykonaj.

  1. Aby wdrożyć funkcje, uruchom to polecenie:

     firebase deploy --only functions
     

    Po uruchomieniu tego polecenia interfejs Firebase CLI wyświetli adres URL wszystkich punktów końcowych funkcji HTTP. W terminalu powinien pojawić się wiersz podobny do tego:

    Function URL (addMessage): https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage
    

    Adres URL zawiera identyfikator projektu oraz region funkcji HTTP. Chociaż nie musisz się tym teraz przejmować, niektóre funkcje HTTP w środowisku produkcyjnym powinny określać lokalizację, aby zminimalizować opóźnienie sieci.

    Jeśli napotkasz błędy dostępu, takie jak „Nie można autoryzować dostępu do projektu”, sprawdź aliasowanie projektu.

  2. Korzystając z adresu URL wygenerowanego przez interfejs CLI, dodaj parametr zapytania tekstowego i otwórz go w przeglądarce:

    https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage?text=uppercasemetoo
    

    Funkcja wykonuje działanie i przekierowuje przeglądarkę do Firebasekonsoli w lokalizacji bazy danychFirebase, w której przechowywany jest ciąg tekstowy. To zdarzenie zapisu wywołuje funkcję „make uppercase”, która zapisuje ciąg znaków w wersji pisanej wielkimi literami.

Po wdrożeniu i wykonaniu funkcji możesz wyświetlić logi w Google Cloudkonsoli. Jeśli chcesz usunąć funkcje w środowisku deweloperskim lub produkcyjnym, użyj interfejsu wiersza poleceń Firebase.

W środowisku produkcyjnym możesz zoptymalizować wydajność funkcji i kontrolować koszty, ustawiając minimalną i maksymalną liczbę instancji do uruchomienia. Więcej informacji o tych opcjach środowiska wykonawczego znajdziesz w sekcji Kontrolowanie skalowania.

Dalsze kroki

W tej dokumentacji znajdziesz więcej informacji o tym, jak zarządzać funkcjami w przypadku Cloud Functions, a także jak obsługiwać wszystkie typy zdarzeń obsługiwane przez Cloud Functions.

Aby dowiedzieć się więcej o Cloud Functions, możesz też wykonać te czynności: