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


Aby rozpocząć korzystanie z Cloud Functions, zapoznaj się z tym samouczkiem, który zaczyna się od wymaganych zadań konfiguracyjnych, a kończy na tworzeniu, testowaniu i wdrażaniu 2 powiązanych ze sobą funkcji:

  • Funkcja „dodaj wiadomość”, która ujawnia adres URL przyjmujący wartość tekstową i zapisuje ją w Cloud Firestore.
  • Funkcja „make uppercase”, która jest wywoływana po zapisie za pomocą funkcji 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

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

W następnych sekcjach tego samouczka znajdziesz szczegółowe instrukcje kompilowania, testowania i wdrażania przykładowej aplikacji.

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 ją z menu.

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

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

  3. Kliknij Dalej.

  4. (Opcjonalnie) Skonfiguruj w projekcie Google Analytics, aby optymalnie korzystać z tych usług Firebase:

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

    Jeśli tworzysz nowe konto, wybierz lokalizację raportowania Analytics, a następnie zaakceptuj ustawienia udostępniania danych i warunki korzystania z usługi Google Analytics w swoim projekcie.

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

Firebase automatycznie udostępnia zasoby dla Twojego projektu Firebase. Po zakończeniu procesu wyświetli się strona podsumowania projektu Firebase w konsoli Firebase.

Konfigurowanie środowiska i wiersza poleceń Firebase

Node.js

Do tworzenia funkcji potrzebujesz środowiska Node.js, a do wdrażania funkcji w środowisku wykonawczym Cloud Functions – interfejsu wiersza poleceń Firebase. Do instalowania Node.js i npm zalecamy użycie menedżera wersji Node.js.

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

npm install -g firebase-tools

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

Python

Do pisania funkcji potrzebne będzie środowisko Pythona, a do wdrażania funkcji w środowisku wykonawczym Cloud Functions – interfejs 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 inicjujesz pakiet SDK Firebase w przypadku Cloud Functions, tworzysz pusty projekt zawierający zależności i minimalny przykładowy kod. Jeśli używasz Node.js, do tworzenia funkcji możesz użyć TypeScript lub JavaScript. W tym samouczku 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. Otwórz katalog projektu Firebase.
  3. Uruchom firebase init firestore. W tym samouczku możesz zaakceptować wartości domyślne, gdy pojawi się prośba o reguły i pliki indeksu Firestore. Jeśli usługa Cloud Firestore nie była jeszcze używana w tym projekcie, musisz też wybrać tryb początkowy i lokalizację dla Firestore zgodnie z opisem w sekcji Pierwsze kroki z Cloud Firestore.
  4. Uruchom firebase init functions. Narzędzie wiersza poleceń wyświetli prośbę o wybranie istniejącej bazy kodu lub zainicjowanie i nazwanie nowej. Na początku wystarczy jedna baza kodu w domyślnej lokalizacji. Później, gdy Twoja implementacja się rozrośnie, możesz uporządkować funkcje w bazach kodu.
  5. Interfejs wiersza poleceń udostępnia te opcje obsługi języka:

    • JavaScript
    • TypeScript
    • Python

    Na potrzeby tego samouczka wybierz JavaScript lub Python. Informacje o tworzeniu kodu w TypeScript znajdziesz w artykule Tworzenie funkcji za pomocą 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 Node.js plik package.json utworzony podczas inicjalizacji 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

Importowanie wymaganych modułów i inicjowanie aplikacji

Po wykonaniu zadań konfiguracyjnych możesz otworzyć katalog źródeł i rozpocząć dodawanie kodu zgodnie z instrukcjami podanymi w następnych sekcjach. 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.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 wprowadzić zmiany Cloud Firestore. Wszędzie tam, gdzie jest dostępny pakiet Admin SDK (jak w przypadku FCM, AuthenticationFirebase Realtime Database), stanowi on potężne narzędzie do integracji Firebase za pomocą Cloud Functions.

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

Dodaj funkcję „Dodaj wiadomość”

W przypadku funkcji „add message” 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 „add message” 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 jak funkcje wywoływane), dlatego odpowiedź należy wysłać tak szybko, jak to możliwe, i odłożyć wykonanie kodu za pomocą funkcji 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.

Dodaj funkcję „zapisywanie 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 „robij duże litery” jest wykonywana po zapisaniu elementu Cloud Firestore, co oznacza, że dokument 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 wywołuje wywołanie zwrotne po każdym dodaniu nowych wiadomości.

W Node.js funkcje sterowane zdarzeniami, takie jak zdarzenia Cloud Firestore, są asynchroniczne. Funkcja wywołania zwrotnego powinna zwracać wartość null, obiekt lub obietnica. Jeśli nie zwrócisz niczego, funkcja zostanie przerwana, co spowoduje błąd i ponownie podjęta próba. Zapoznaj się z artykułem Synchronizacja, asynchroniczność i obietnice.

Emulowanie wykonania funkcji

Firebase Local Emulator Suite pozwala tworzyć i testować aplikacje na komputerze lokalnym zamiast wdrażać je w projekcie Firebase. Zalecamy testowanie lokalne podczas tworzenia aplikacji, ponieważ zmniejsza to ryzyko błędów w kodzie, które mogą potencjalnie generować koszty w środowisku produkcyjnym (np. nieskończona pętla).

Aby emulować funkcje:

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

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

    1. MY_PROJECT zostanie zastąpiony 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ć wiadomość „uppercaseme” na wiadomość niestandardową.

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

  5. Wyświetl efekty działania funkcji w sekcji Emulator Suite UI:

    1. Na karcie Logi powinny pojawić się nowe logi wskazujące, że funkcje HTTP zostały wykonane pomyślnie:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. Na karcie Firestore powinien pojawić się dokument zawierający oryginalną wiadomość oraz jej wersję z wielkimi literami (jeśli oryginalna wiadomość brzmiała „uppercaseme”, zobaczysz „UPPERCASEME”).

Wdrażanie funkcji w środowisku produkcyjnym

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

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

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

     firebase deploy --only functions
     

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

    Jeśli wystąpią błędy dostępu, takie jak „Nie można 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 jest wykonywana i przekierowuje przeglądarkę do konsoli Firebase w lokalizacji bazy danych, w której przechowywany 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 wykonywaniu funkcji możesz wyświetlać dzienniki w konsoli Google Cloud. Jeśli musisz usunąć funkcje w fazie programowania lub produkcji, użyj interfejsu wiersza poleceń Firebase.

W środowisku produkcyjnym możesz optymalizować wydajność funkcji i kontrolować koszty, ustawiając minimalną i maksymalną liczbę instancji. Więcej informacji o tych opcjach w czasie wykonywania znajdziesz w artykule Kontrolowanie zachowania skalowania.

Dalsze kroki

W tej dokumentacji znajdziesz więcej informacji o zarządzaniu funkcjami w przypadku usługi Cloud Functions, a także o obsługiwaniu wszystkich typów zdarzeń obsługiwanych przez tę usługę.Cloud Functions

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