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


Aby zacząć korzystać z Cloud Functions, skorzystaj z tego samouczka, który zaczyna od wymaganych zadań konfiguracyjnych oraz obejmuje tworzenie, testowanie i wdrażanie 2 powiązanych funkcji:

  • Funkcja dodawania wiadomości, która ujawnia adres URL przyjmujący wartość tekstową i zapisuje ją w Cloud Firestore.
  • Funkcja „pisz wielkimi literami”, która aktywuje się podczas zapisu w Cloud Firestore i przekształca tekst na wielkie litery.

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

Node.js

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

Python

# 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

Wybraliśmy dla tego przykładu funkcje Cloud Firestore i wywoływane przez HTTP, ponieważ te aktywatory działające w tle można dokładnie przetestować za pomocą Pakietu emulatorów lokalnych Firebase. Ten zestaw narzędzi obsługuje też aktywatory Realtime Database, Cloud Storage, PubSub, Auth i możliwe do wywołania HTTP. Inne typy aktywatorów działających w tle, takie jak aktywatory Zdalnej konfiguracji i TestLab, można testować interaktywnie przy użyciu zestawów narzędzi, które nie zostały opisane na tej stronie.

W poniższych sekcjach tego samouczka znajdziesz szczegółowe instrukcje dotyczące kompilacji, testowania i wdrażania przykładu.

Tworzenie projektu Firebase

  1. W konsoli Firebase kliknij Dodaj projekt.

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

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

  2. W razie potrzeby przeczytaj i zaakceptuj warunki korzystania z Firebase.

  3. Kliknij Dalej.

  4. (Opcjonalnie) Skonfiguruj Google Analytics w swoim projekcie, by zapewnić optymalną wygodę korzystania z tych usług Firebase:

    Wybierz istniejące konto Google Analytics lub utwórz nowe.

    Po utworzeniu nowego konta wybierz lokalizację raportowania Analytics, a następnie zaakceptuj w swoim projekcie ustawienia udostępniania danych i warunki korzystania z Google Analytics.

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

Firebase automatycznie udostępnia zasoby projektu Firebase. Po zakończeniu tego procesu otworzy się strona przeglądu Twojego projektu Firebase w konsoli Firebase.

Konfigurowanie środowiska i interfejsu wiersza poleceń Firebase

Node.js

Do pisania funkcji potrzebujesz środowiska Node.js, a do wdrażania funkcji w środowisku wykonawczym Cloud Functions – interfejsu wiersza poleceń Firebase. Do instalacji Node.js i npm zalecamy korzystanie z Menedżera wersji węzłów.

Po zainstalowaniu Node.js i npm zainstaluj interfejs wiersza poleceń Firebase za pomocą preferowanej metody. Aby zainstalować interfejs wiersza poleceń przy użyciu npm, użyj:

npm install -g firebase-tools

Spowoduje to zainstalowanie dostępnego globalnie polecenia Firebase. Jeśli polecenie nie powiedzie się, być może trzeba zmienić uprawnienia npm. Aby zaktualizować aplikację firebase-tools do najnowszej wersji, uruchom to samo polecenie ponownie.

Python

Do pisania funkcji potrzebujesz środowiska Pythona, a do wdrażania funkcji w środowisku wykonawczym Cloud Functions – interfejsu wiersza poleceń Firebase. Do izolowania zależności zalecamy użycie metody venv. Obsługiwane są Python w wersjach 3.10 i 3.11.

Po zainstalowaniu Pythona zainstaluj interfejs wiersza poleceń Firebase za pomocą preferowanej metody.

Zainicjuj projekt

Gdy zainicjujesz pakiet SDK Firebase dla Cloud Functions, utworzysz pusty projekt zawierający zależności i minimalną ilość przykładowego kodu. Jeśli używasz Node.js, do tworzenia funkcji możesz wybrać TypeScript lub JavaScript. 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 wiersza poleceń Firebase.
  2. Przejdź do katalogu projektów 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 oraz plików indeksu. Jeśli w tym projekcie nie używano jeszcze Cloud Firestore, musisz też wybrać tryb uruchamiania i lokalizację Firestore zgodnie z opisem w artykule Pierwsze kroki z Cloud Firestore.
  4. Uruchom firebase init functions. W interfejsie wiersza poleceń wyświetli się prośba o wybranie istniejącej bazy kodu lub zainicjowanie i nazwa nowej. Na początek wystarczy pojedyncza baza kodu w domyślnej lokalizacji. W miarę rozwijania implementacji możesz chcieć uporządkować funkcje w bazach kodu.
  5. Interfejs wiersza poleceń zawiera te opcje obsługi języków:

    • JavaScript
    • TypeScript
    • Python

    Na potrzeby tego samouczka wybierz JavaScript lub Python. Informacje o tworzeniu treści w języku TypeScript znajdziesz w artykule Zapisywanie funkcji za pomocą języka TypeScript.

  6. Interfejs wiersza poleceń pozwala zainstalować zależności. Można to bezpiecznie odrzucić, jeśli chcesz zarządzać zależnościami w inny sposób.

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

Node.js

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 środowiska Node.js plik package.json utworzony podczas inicjowania zawiera ważny klucz: "engines": {"node": "18"}. Określa wersję Node.js do zapisywania i wdrażania funkcji. Możesz wybrać inne obsługiwane wersje.

Python

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 w sposób opisany w kolejnych sekcjach. W tym przykładzie Twój projekt musi zaimportować moduły Cloud Functions i Admin SDK. Dodaj do pliku źródłowego wiersze podobne do tych:

Node.js

// 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();

Python

# 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, z której można wprowadzać zmiany w Cloud Firestore. Wszędzie tam, gdzie dostępna jest obsługa pakietu Admin SDK, tak jak w przypadku FCM, uwierzytelniania czy Bazy danych czasu rzeczywistego Firebase, zapewnia skuteczny sposób integracji Firebase za pomocą Cloud Functions.

Interfejs wiersza poleceń Firebase automatycznie instaluje pakiet Firebase Admin SDK i pakiet SDK Firebase dla Cloud Functions po zainicjowaniu projektu. Więcej informacji o dodawaniu do projektu bibliotek zewnętrznych znajdziesz w artykule Obsługa zależności.

Dodawanie funkcji „dodaj wiadomość”

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

Node.js

// 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.`});
});

Python

@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 „dodaj wiadomość” jest punktem końcowym HTTP. Każde żądanie skierowane do punktu końcowego powoduje przekazanie obiektów żądań i odpowiedzi do modułu obsługi żądania na platformie (onRequest() lub on_request).

Funkcje HTTP są synchroniczne (podobnie do funkcji wywoływanych), dlatego odpowiedź należy wysłać jak najszybciej i opóźnić pracę z użyciem Cloud Firestore. Funkcja HTTP „dodaj wiadomość” przekazuje wartość tekstową do punktu końcowego HTTP i wstawia ją do bazy danych pod ścieżką /messages/:documentId/original.

Dodaj funkcję „pisz wielkimi literami”

W przypadku funkcji „stosuj wielkie litery” do pliku źródłowego dodaj te wiersze:

Node.js

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

Python

@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 „stosuj wielkie litery” jest wykonywana przy zapisie do Cloud Firestore, określając dokument, który ma nasłuchiwać. Jeśli zależy Ci na wydajności, podaj jak najwięcej szczegółów.

Nawiasy klamrowe (np. {documentId}) – przestrzenne „parametry” i symbole wieloznaczne, które ujawniają pasujące dane w wywołaniu zwrotnym. Cloud Firestore aktywuje wywołanie zwrotne po każdym dodaniu nowych wiadomości.

W środowisku Node.js funkcje oparte na zdarzeniach, takie jak zdarzenia Cloud Firestore, są asynchroniczne. Funkcja wywołania zwrotnego powinna zwracać wartość null, Object lub Promise. Jeśli niczego nie zwrócisz, funkcja przekroczy limit czasu, sygnalizując błąd i jest ponawiana. Zobacz Synchronizacja, asynchroniczne i obietnice.

Emuluj wykonywanie funkcji

Pakiet emulatorów lokalnych Firebase pozwala tworzyć i testować aplikacje na komputerze lokalnym zamiast wdrażać je w projekcie Firebase. Zdecydowanie zalecamy testowanie lokalne w trakcie programowania, m.in. dlatego, że zmniejsza to ryzyko wystąpienia błędów w kodzie, które mogą skutkować kosztami w środowisku produkcyjnym (na przykład nieskończonej pętli).

Aby emulować funkcje:

  1. Uruchom firebase emulators:start i sprawdź dane wyjściowe adresu URL interfejsu użytkownika Pakietu emulatorów. Domyślnie jest to localhost:4000, ale może być hostowany na innym porcie komputera. Wpisz ten adres URL w przeglądarce, aby otworzyć interfejs użytkownika Pakietu emulatorów.

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

    1. Pole MY_PROJECT zostanie zastąpione identyfikatorem projektu.
    2. Port może się różnić w zależności od komputera lokalnego.
  3. Dodaj ciąg zapytania ?text=uppercaseme na końcu adresu URL funkcji. Powinien wyglądać podobnie do tego: http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme. Opcjonalnie możesz zmienić komunikat „wielkie litery” na niestandardowy.

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

  5. Sprawdź efekty funkcji w interfejsie użytkownika Pakietu emulatorów:

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

      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ę pisaną wielkimi literami (jeśli wcześniej była pisana wielkimi literami, zobaczysz „WIELKIE LITERY”).

Wdrażanie funkcji w środowisku produkcyjnym

Gdy funkcje w emulatorze będą działać zgodnie z oczekiwaniami, możesz przejść do wdrażania, testowania i uruchamiania ich w środowisku produkcyjnym. Pamiętaj, że aby możliwe było wdrożenie w środowisku produkcyjnym, Twój projekt musi być objęty abonamentem Blaze. Zapoznaj się z cennikiem Cloud Functions.

Aby ukończyć samouczek, wdróż funkcje i je wykonaj.

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

     firebase deploy --only functions
     

    Po uruchomieniu tego polecenia interfejs wiersza poleceń Firebase będzie wyświetlać 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. Nie musisz się tym teraz przejmować, ale niektóre produkcyjne funkcje HTTP powinny określać lokalizację, aby zminimalizować opóźnienia sieciowe.

    Jeśli napotkasz błędy dostępu, takie jak „Nie udało się autoryzować dostępu do projektu”, sprawdź aliasy projektu.

  2. Korzystając z danych wyjściowych adresu URL interfejsu wiersza poleceń, dodaj tekstowy parametr zapytania i otwórz go w przeglądarce:

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

    Funkcja uruchamia się i przekierowuje przeglądarkę do konsoli Firebase w lokalizacji bazy danych, w której zapisany jest ciąg tekstowy. To zdarzenie zapisu aktywuje funkcję „stosuj wielkie litery”, która zapisuje ciąg znaków w wersji pisanej wielkimi literami.

Po wdrożeniu i wykonaniu funkcji możesz wyświetlać logi w konsoli Google Cloud. Jeśli chcesz usunąć funkcje w fazie programowania lub produkcji, użyj interfejsu wiersza poleceń Firebase.

W środowisku produkcyjnym warto zoptymalizować wydajność funkcji i kontrolować koszty przez ustawienie minimalnej i maksymalnej liczby instancji do uruchomienia. Więcej informacji o tych opcjach środowiska wykonawczego znajdziesz w artykule o sterowaniu skalowaniem.

Dalsze kroki

W tej dokumentacji znajdziesz więcej informacji o zarządzaniu funkcjami w Cloud Functions oraz o obsłudze wszystkich typów zdarzeń obsługiwanych przez Cloud Functions.

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