จัดระเบียบฟังก์ชันหลายรายการ


เมื่อผสานรวม Cloud Functions เข้ากับโปรเจ็กต์ โค้ดอาจขยายให้มีฟังก์ชันอิสระหลายรายการ คุณอาจมีฟังก์ชันมากเกินไปที่จะใส่ไว้ในไฟล์เดียวได้ หรือทีมต่างๆ อาจใช้กลุ่มฟังก์ชันที่แตกต่างกัน ซึ่งอาจทำให้ทีมหนึ่งเขียนทับหรือลบฟังก์ชันของอีกทีมโดยไม่ได้ตั้งใจ Cloud Functions มีวิธีต่างๆ ในการจัดระเบียบโค้ดเพื่อให้ไปยังส่วนต่างๆ และดูแลรักษาฟังก์ชันได้ง่ายขึ้น

จัดระเบียบฟังก์ชันในฐานโค้ด

คุณสามารถใช้พร็อพเพอร์ตี้ codebase ของออบเจ็กต์การกําหนดค่าฟังก์ชันใน firebase.json เพื่อจัดการคอลเล็กชันฟังก์ชันจํานวนมากในรีโพซิทรีหรือแพ็กเกจย่อยหลายรายการภายในการตั้งค่า Monorepo ของรีโพซิทรีเดียว ดังนี้

# firebase.json
"functions": {
  "codebase": "my-codebase"
  # NOTE: Codebase must be less than 63 characters and can contain only
  # lowercase letters, numeric characters, underscores, and dashes.
}

Firebase CLI รองรับพร็อพเพอร์ตี้ codebase ตั้งแต่เวอร์ชัน 10.7.1 ขึ้นไป

การจัดการที่เก็บหลายรายการ

พร็อพเพอร์ตี้ codebase ช่วยลดความซับซ้อนในการจัดการที่เก็บหลายแห่ง มาดูกรณีที่คุณมีที่เก็บ 2 แห่งที่แตกต่างกันซึ่งทำให้ฟังก์ชันใช้งานได้ในโปรเจ็กต์ Firebase เดียวกันกัน

$  tree .
├── repoA
│   ├── firebase.json
│   └── functions
│       ├── index.js
│       └── package.json
└── repoB
    ├── firebase.json
    └── functions
        ├── index.js
        └── package.json

หากไม่มีคำอธิบายประกอบของโค้ดเบสของ Firebase CLI จะแจ้งให้คุณลบฟังก์ชันที่กำหนดไว้ในที่เก็บอื่นในขณะที่ทำให้ใช้งานได้

$ (cd repoA && firebase deploy --only functions)
...
i  functions: preparing functions directory for uploading...
  functions: functions folder uploaded successfully
The following functions are found in your project but do not exist in your local source code:
        fn1FromRepoB
        fn2FromRepoB
        ...
? Would you like to proceed with deletion? Selecting no will continue the rest of the deployments. (y/N)

คุณหลีกเลี่ยงปัญหานี้ได้โดยการเพิ่มคำอธิบายประกอบโค้ดเบสที่ไม่ซ้ำกันในส่วนการกําหนดค่าฟังก์ชันของ firebase.json ในที่เก็บโปรเจ็กต์แต่ละแห่ง ดังนี้

# repoA/firebase.json
"functions": {
  "codebase": "repo-a"
}

# repoB/firebase.json
"functions": {
  "codebase": "repo-b"
}

เมื่อใช้คำอธิบายประกอบของโค้ดเบสของ Firebase CLI จะไม่แจ้งให้คุณลบฟังก์ชันที่กำหนดนอกที่เก็บทันทีอีกต่อไป

$ (cd repoA && firebase deploy --only functions)
...
i  functions: preparing functions directory for uploading...
  functions: functions folder uploaded successfully
#  Gleefully ignores functions from repoB
i  functions: creating Node.js 16 function fnFromRepoA (us-central1)...
  Deploy Complete!

การจัดการแพ็กเกจแหล่งที่มาหลายรายการ (Monorepo)

พร็อพเพอร์ตี้ codebase ช่วยให้จัดการแพ็กเกจแหล่งที่มาหลายรายการในที่เก็บข้อมูลแห่งเดียวได้ง่ายขึ้น มาดูกรณีที่คุณมีไดเรกทอรีโปรเจ็กต์ Firebase ที่มีการกำหนดฟังก์ชันกระจายอยู่ในแพ็กเกจย่อยหลายรายการกัน

$  tree .
├── firebase.json
├── teamA
│   ├── index.js
│   └── package.json
└── teamB
    ├── index.js
    └── package.json

การตั้งค่านี้เหมาะกับกรณีการใช้งานต่อไปนี้

  • คุณมีการตั้งค่า monorepo และมีทีมต่างๆ จัดการคําจํากัดความของฟังก์ชันของตนเองในแพ็กเกจแยกต่างหาก
  • คุณมีฟังก์ชันที่มีความเชื่อมโยงภายนอกอย่างมากและใช้เวลาในการเริ่มต้นนาน และต้องการแยกฟังก์ชันนั้นออกจากฟังก์ชันอื่นๆ ที่ไวต่อเวลาในการตอบสนอง

หากต้องการรองรับการตั้งค่า monrepo เช่นนี้ ให้กําหนดการกําหนดค่าฟังก์ชันหลายรายการใน firebase.json ดังนี้

"functions": [
  {
    "source": "teamA",
    "codebase": "team-a"
  },
  {
    "source": "teamB",
    "codebase": "team-b"
  },
]

เมื่อใช้การกำหนดค่านี้ Firebase CLI จะทําให้ฟังก์ชันจากแพ็กเกจทั้งหมดใช้งานได้ในคําสั่งทำให้ใช้งานได้คําเดียว

$ firebase deploy --only functions
i  deploying functions
i  functions: preparing codebase team-a for deployment
i  functions: preparing codebase team-b for deployment
i  functions: creating Node.js 16 function team-a:helloATeam(us-central1)...
i  functions: creating Node.js 16 function team-b:helloBTeam(us-central1)...
...

นอกจากนี้ คุณยังทําให้ใช้งานได้กับฐานโค้ดที่เฉพาะเจาะจงได้ด้วย โดยทําดังนี้

$ firebase deploy --only functions:team-b
i  deploying functions
i  functions: preparing codebase team-b for deployment
i  functions: updating Node.js 16 function team-b:helloBTeam(us-central1)...
...

เขียนฟังก์ชันในหลายไฟล์

เมื่อเริ่มต้นใช้งาน Cloud Functions คุณอาจใส่ฟังก์ชันแรกๆ 2-3 รายการไว้ในไฟล์เดียว

index.js

const functions = require('firebase-functions/v1');
exports.foo = functions.https.onRequest((request, response) => {
  // ...
});
exports.bar = functions.https.onRequest((request, response) => {
  // ...
});

main.py

from firebase_functions import https_fn

@https_fn.on_request()
def foo(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello foo!")

@https_fn.on_request()
def bar(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello bar!")

ซึ่งอาจทำให้จัดการได้ยากหากมีฟังก์ชันมากกว่า 2-3 รายการ แต่คุณสามารถใส่ตรรกะทั้งหมดของฟังก์ชันแต่ละรายการไว้ในไฟล์ของตัวเองและใช้ไฟล์ต้นฉบับเป็นรายการการส่งออกได้ ดังนี้

Node.js

foo.js

const functions = require('firebase-functions/v1');
exports.foo = functions.https.onRequest((request, response) => {
  // ...
});

bar.js

const functions = require('firebase-functions/v1');
exports.bar = functions.https.onRequest((request, response) => {
  // ...
});

index.js

const foo = require('./foo');
const bar = require('./bar');
exports.foo = foo.foo;
exports.bar = bar.bar;

Python

foo.py

from firebase_functions import https_fn

@https_fn.on_request()
def foo(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello foo!")

bar.py

from firebase_functions import https_fn

@https_fn.on_request()
def bar(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello foo!")

main.py

from fn_impl.foo import *
from fn_impl.bar import *

การตั้งค่านี้ถือว่าโครงสร้างไดเรกทอรีโปรเจ็กต์มีลักษณะดังต่อไปนี้

my-project
├── firebase.json
└── functions
    ├── fn_impl
    │   ├── __init__.py
    │   ├── foo.py
    │   └── bar.py
    ├── main.py
    └── requirements.txt

fn_impl: ตั้งชื่ออะไรก็ได้

__init__.py: ต้องระบุ แต่ปล่อยว่างได้

ฟังก์ชันกลุ่ม

ในโปรเจ็กต์หลายรายการ ฟังก์ชันสามารถแยกออกเป็นกลุ่มตามตรรกะซึ่งควรนำไปใช้งานและดูแลรักษาร่วมกัน เช่น คุณอาจมีกลุ่มฟังก์ชันที่ใช้สำหรับการรายงานเมตริก ดังนี้

metrics.js


const functions = require('firebase-functions/v1');
exports.usageStats = functions.https.onRequest((request, response) => {
  // ...
});
exports.nightlyReport = functions.https.onRequest((request, response) => {
  // ...
});

คุณสามารถจัดฟังก์ชันเหล่านี้ไว้ในกลุ่มเมื่อส่งออกในindex.js ไฟล์

index.js


// Export both functions from metrics.js in the "metrics" group:
//  - metrics-usageStats
//  - metrics-nightlyReport
exports.metrics = require('./metrics');

เมื่อทําให้การเผยแพร่ใช้งานได้ ฟังก์ชันจะมีชื่อกลุ่มอยู่ข้างหน้า ดังนั้นในตัวอย่างนี้ ฟังก์ชันจะมีชื่อว่า metrics-usageStats และ metrics-nightlyReport

เมื่อทําให้ฟังก์ชันใช้งานได้ คุณสามารถจํากัดการดําเนินการไว้ที่กลุ่มเดียวได้ ดังนี้


firebase deploy --only functions:metrics

ขั้นตอนถัดไป

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Cloud Functions ได้ที่