טיפול ביחסי תלות

בחירת שפה: ‫Node.js Python

פונקציה של Cloud Functions יכולה להשתמש במודולים חיצוניים ובתלויות מקומיות. האופן שבו מציינים ומנהלים תלויות משתנה בהתאם לשפת זמן הריצה.

Node.js

מותר להשתמש בפונקציה במודולים חיצוניים של Node.js וגם בנתונים מקומיים. התלויות ב-Node.js מנוהלות באמצעות npm ומופיעות בקובץ מטא-נתונים בשם package.json. סביבות זמן הריצה של Node.js ב-Cloud Functions תומכות בהתקנה באמצעות npm,‏ yarn או pnpm.

כדי לציין תלות בפונקציה, מוסיפים אותה לקובץ package.json.

בדוגמה הזו, תלות מופיעה בקובץ package.json:

{
  "dependencies": {
    "escape-html": "^1.0.3"
  }
}

לאחר מכן מייבאים את התלות בפונקציה:

JavaScript

const onRequest = require("firebase-functions/https");
const escapeHtml = require("escape-html");

// Return a greeting with the input HTML-escaped.
exports.hello = onRequest((req, res) => {
  res.send(`Hello ${escapeHtml(req.query.name || req.body.name || "World")}!`);
});

TypeScript

import { onRequest } from "firebase-functions/https";
import * as escapeHtml from "escape-html";

// Return a greeting with the input HTML-escaped.
export let hello = onRequest((req, res) => {
  res.send(`Hello ${escapeHtml(req.query.name || req.body.name || "World")}!`);
});

הכללת מודולים מקומיים של Node.js

אפשר גם לכלול מודולים מקומיים של Node.js כחלק מהפונקציה. כדי לעשות את זה, צריך להצהיר על המודול ב-package.json באמצעות הקידומת file:. בדוגמה הבאה, mymodule הוא שם המודול ו-mymoduledir הוא הספרייה שמכילה את המודול:

{
  "dependencies": {
    "mymodule": "file:mymoduledir"
  }
}

הקוד של המודול המקומי הזה צריך להיות מאוחסן במקום אחר ולא בתיקייה node_modules בספריית הבסיס של הפונקציה.

שלבים נוספים ל-TypeScript

השימוש ב-TypeScript הכי מועיל כשמשתמשים בספריות שיש בהן מידע על סוגים. כך TypeScript יכולה לזהות שגיאות תחביר, ועורכי קוד יכולים לתת הצעות טובות יותר להשלמה אוטומטית. חלק מהספריות, כמו firebase-admin ו-firebase-functions, מגיעות עם הגדרות TypeScript כלולות.

הרבה ספריות לא מספקות הגדרת TypeScript משלהן. בפרויקט DefinitelyTyped יש הגדרות שמתעדכנות על ידי הקהילה עבור ספריות הצמתים הפופולריות ביותר. ‫DefinitelyTyped מפרסמת את ההגדרות האלה באותו שם חבילת NPM, אבל בתוך הארגון '‎@types'. לדוגמה, אפשר להתקין את פרטי הסוג של הספרייה uuid באמצעות הפקודה הבאה:

npm install @types/uuid

כשתכירו טוב יותר את TypeScript, תוכלו לשלב בין שתי ההתקנות:

npm install uuid @types/uuid

סוג התלות צריך להיות זהה לסוג התלות בספרייה. לדוגמה, לא מומלץ לשמור את uuid כתלות רגילה ואת @types/uuid כתלות לפיתוח או כתלות עמיתים.

טעינת מודולים של Node.js

משתמשים בפונקציה Node.js require() כדי לטעון כל מודול Node.js שהתקנתם. אפשר גם להשתמש בפונקציה require() כדי לייבא קבצים מקומיים שאתם פורסים לצד הפונקציה.

אם אתם כותבים פונקציות ב-TypeScript, אתם יכולים להשתמש בהצהרה import באותו אופן כדי לטעון כל מודול Node.js שהתקנתם.

שימוש במודולים פרטיים

כדי להשתמש במודול npm פרטי, צריך לספק הגדרות לאימות מול המאגר בקובץ .npmrc בתיקייה של הפונקציה. אם אתם משתמשים ב-Yarn בגרסה 2 ומעלה כמנהל החבילות, שם הקובץ הוא .yarnrc.yml.

מודולים פרטיים מ-Artifact Registry

מאגר חבילות Node.js ב-Artifact Registry יכול לארח מודולים פרטיים של הפונקציה. כשפורסים פונקציה של Google Cloud Functions, תהליך ה-build יוצר באופן אוטומטי פרטי כניסה ל-Artifact Registry עבור חשבון השירות ב-Cloud Build. צריך לכלול רק את מאגר Artifact Registry ב-.npmrc בלי ליצור פרטי כניסה נוספים. לדוגמה:

@SCOPE:registry=https://REGION_ID-npm.pkg.dev/PROJECT_ID/REPOSITORY_NAME
//REGION_ID-npm.pkg.dev/PROJECT_ID/REPOSITORY_NAME:always-auth=true

הגישה הזו פועלת גם במנהל החבילות Yarn v1. אם אתם משתמשים ב-Yarn בגרסה 2 ומעלה, אתם צריכים רק לציין את מאגר Artifact Registry ב-.yarnrc.yml בלי פרטי כניסה נוספים. לדוגמה:

npmScopes:
  SCOPE:
    npmRegistryServer: https://REGION_ID-npm.pkg.dev/PROJECT_ID/REPOSITORY_NAME
    npmAlwaysAuth: true

מודולים פרטיים ממאגרים אחרים

במסמכי התיעוד של npm מוסבר איך ליצור טוקנים מותאמים אישית של גישת קריאה בלבד. אנחנו לא ממליצים להשתמש בקובץ .npmrc שנוצר בספריית הבית כי הוא מכיל טוקן לקריאה ולכתיבה. הרשאות כתיבה לא נדרשות במהלך הפריסה, והן עלולות להוות סיכון אבטחה.

אם אתם לא משתמשים במאגרים פרטיים, אל תכללו את הקובץ .npmrc, כי הוא עלול להאריך את זמן הפריסה של הפונקציות.

פורמט קובץ

אם אתם משתמשים בקובץ .npmrc כדי להגדיר אסימון אימות בהתאמה אישית, הוא צריך לכלול את השורה שמוצגת למטה.

//REGISTRY_DOMAIN/:_authToken=AUTH_TOKEN

מחליפים את:

  • ‫REGISTRY_DOMAIN: שם הדומיין של מאגר npm פרטי. אם המאגר שלכם מתארח ב-npmjs.org, צריך להגדיר את השדה הזה ל-registry.npmjs.org.
  • ‫AUTH_TOKEN: אסימון ההרשאה של מאגר npm. אפשר להזין את הערך המילולי של הטוקן או את מחרוזת הטקסט ${NPM_TOKEN}, שבה npm מוחלף בערך הטוקן בפועל מהסביבה.

    אפשר להגדיר את משתנה הסביבה $NPM_TOKEN באמצעות הארגומנט --set-build-env-vars של הפקודה gcloud functions deploy. לפרטים נוספים על אסימון האימות של NPM, אפשר לעיין במדריך של NPM בנושא מודולים פרטיים.


Python

יש שתי דרכים לציין יחסי תלות עבור Cloud Functions שנכתבו ב-Python: שימוש בקובץ requirements.txt של מנהל החבילות pip או אריזה של יחסי תלות מקומיים לצד הפונקציה.

אין תמיכה בציון יחסי תלות באמצעות התקן Pipfile/Pipfile.lock. הפרויקט לא צריך לכלול את הקבצים האלה.

ציון יחסי תלות באמצעות PIP

יחסי תלות ב-Python מנוהלים באמצעות pip ומבוטאים בקובץ מטא-נתונים שנקרא requirements.txt. הקובץ הזה צריך להיות באותה ספרייה כמו קובץ main.py שמכיל את קוד הפונקציה.

כשפורסים או פורסים מחדש את הפונקציה, Cloud Functions משתמש ב-pip כדי להוריד ולהתקין את הגרסה העדכנית של התלות שהוגדרה בקובץ requirements.txt. הקובץ requirements.txt מכיל שורה אחת לכל חבילה. כל שורה מכילה את שם החבילה, ואת הגרסה המבוקשת (אופציונלי). פרטים נוספים זמינים במקור המידע requirements.txt.

כדי למנוע השפעה על ה-build שלכם כתוצאה משינויים בגרסת התלות, כדאי להצמיד את חבילות התלות לגרסה ספציפית.

קובץ requirements.txt לדוגמה:

functions-framework
requests==2.20.0
numpy

אריזת יחסי תלות מקומיים

אפשר גם לארוז ולפרוס תלויות לצד הפונקציה. הגישה הזו שימושית אם התלות לא זמינה דרך מנהל החבילות pip או אם הגישה לאינטרנט בסביבת Cloud Functions מוגבלת.

לדוגמה, אפשר להשתמש במבנה ספריות כמו זה שמופיע בהמשך:

myfunction/
├── main.py
└── localpackage/
    ├── __init__.py
    └── script.py

אחר כך אפשר לייבא את הקוד כרגיל מ-localpackage באמצעות ההצהרה הבאה של import.

# Code in main.py
from localpackage import script

חשוב לדעת: בגישה הזו לא יופעלו קבצי setup.py. עדיין אפשר לארוז חבילות עם הקבצים האלה, אבל יכול להיות שהן לא יפעלו בצורה תקינה ב-Cloud Functions.