แอปที่ใช้ฟังก์ชันรุ่นที่ 1 อยู่ในปัจจุบันควรพิจารณาย้ายข้อมูลไปยังรุ่นที่ 2 โดยใช้วิธีการในคู่มือนี้ ฟังก์ชันรุ่นที่ 2 ใช้ Cloud Run เพื่อให้ประสิทธิภาพที่ดียิ่งขึ้น การกำหนดค่าที่ดีขึ้น การตรวจสอบที่ดียิ่งขึ้น และอื่นๆ
ตัวอย่างในหน้านี้ถือว่าคุณใช้ JavaScript กับโมดูล CommonJS (การนําเข้าสไตล์ require
) แต่หลักการเดียวกันนี้ใช้กับ JavaScript กับ ESM (การนําเข้าสไตล์ import … from
) และ TypeScript ได้
กระบวนการย้ายข้อมูล
ฟังก์ชันรุ่นที่ 1 และรุ่นที่ 2 สามารถอยู่ร่วมกันในไฟล์เดียวกันได้ วิธีนี้ช่วยให้คุณย้ายข้อมูลทีละส่วนได้อย่างง่ายดายเมื่อพร้อม เราขอแนะนําให้ย้ายข้อมูลทีละฟังก์ชัน โดยทําการทดสอบและการยืนยันก่อนดําเนินการต่อ
ตรวจสอบเวอร์ชัน Firebase CLI และ firebase-function
ตรวจสอบว่าคุณใช้ Firebase CLI เวอร์ชัน 12.00
เป็นอย่างน้อย และ firebase-functions
เวอร์ชัน 4.3.0
เวอร์ชันที่ใหม่กว่าจะรองรับทั้งรุ่นที่ 1 และรุ่นที่ 2
อัปเดตการนําเข้า
ฟังก์ชันรุ่นที่ 2 ที่นําเข้าจากแพ็กเกจย่อย v2
ใน firebase-functions
SDK
เส้นทางการนําเข้าที่แตกต่างกันนี้เป็นข้อมูลทั้งหมดที่ Firebase CLI ต้องการเพื่อพิจารณาว่าจะทําให้โค้ดฟังก์ชันเป็นฟังก์ชันรุ่นที่ 1 หรือ 2
แพ็กเกจย่อย v2
เป็นโมดูล และเราขอแนะนำให้นำเข้าเฉพาะโมดูลที่คุณต้องการ
ก่อน: รุ่นที่ 1
const functions = require("firebase-functions/v1");
หลัง: รุ่นที่ 2
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
อัปเดตคําจํากัดความของทริกเกอร์
เนื่องจาก SDK รุ่นที่ 2 รองรับการนําเข้าแบบโมดูล ให้อัปเดตคําจํากัดความทริกเกอร์เพื่อแสดงการนําเข้าที่เปลี่ยนแปลงจากขั้นตอนก่อนหน้า
อาร์กิวเมนต์ที่ส่งไปยังการเรียกกลับสําหรับทริกเกอร์บางรายการมีการเปลี่ยนแปลง ในตัวอย่างนี้ โปรดทราบว่าอาร์กิวเมนต์ของ onDocumentCreated
callback ได้รับการรวมไว้ในออบเจ็กต์ event
รายการเดียว นอกจากนี้ ทริกเกอร์บางรายการยังมีฟีเจอร์การกําหนดค่าใหม่ที่สะดวก เช่น ตัวเลือก onRequest
ของทริกเกอร์ cors
ก่อน: รุ่นที่ 1
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
หลัง: รุ่นที่ 2
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
ใช้การกําหนดค่าแบบพารามิเตอร์
ฟังก์ชันรุ่นที่ 2 จะไม่รองรับ functions.config
แต่จะเปลี่ยนไปใช้อินเทอร์เฟซที่ปลอดภัยยิ่งขึ้นสําหรับการกําหนดพารามิเตอร์การกําหนดค่าแบบประกาศภายในโค้ดเบส เมื่อใช้โมดูล params
ใหม่ CLI จะบล็อกการติดตั้งใช้งาน เว้นแต่พารามิเตอร์ทั้งหมดจะมีค่าที่ถูกต้อง เพื่อให้มั่นใจว่าจะไม่มีการติดตั้งใช้งานฟังก์ชันโดยไม่มีการกำหนดค่า
ย้ายข้อมูลไปยังแพ็กเกจย่อย params
หากใช้การกําหนดค่าสภาพแวดล้อมกับ functions.config
อยู่ คุณสามารถย้ายข้อมูลการกําหนดค่าที่มีอยู่ไปยังการกําหนดค่าที่มีพารามิเตอร์ได้
ก่อน: รุ่นที่ 1
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
const date = new Date();
const formattedDate =
date.toLocaleDateString(functions.config().dateformat);
// ...
});
หลัง: รุ่นที่ 2
const {onRequest} = require("firebase-functions/v2/https");
const {defineString} = require("firebase-functions/params");
const dateFormat = defineString("DATE_FORMAT");
exports.date = onRequest((req, res) => {
const date = new Date();
const formattedDate = date.toLocaleDateString(dateFormat.value());
// ...
});
ตั้งค่าพารามิเตอร์
เมื่อคุณทำให้ใช้งานได้เป็นครั้งแรก Firebase CLI จะแจ้งให้ป้อนค่าทั้งหมดของพารามิเตอร์และบันทึกค่าไว้ในไฟล์ dotenv หากต้องการส่งออกค่าในไฟล์ functions.config ให้เรียกใช้ firebase functions:config:export
คุณยังระบุประเภทพารามิเตอร์และกฎการตรวจสอบเพื่อความปลอดภัยเพิ่มเติมได้ด้วย
กรณีพิเศษ: คีย์ API
โมดูล params
ผสานรวมกับ Secret Manager ของ Cloud ซึ่งให้การควบคุมการเข้าถึงแบบละเอียดสำหรับค่าที่มีความละเอียดอ่อน เช่น คีย์ API ดูข้อมูลเพิ่มเติมเกี่ยวกับพารามิเตอร์ลับ
ก่อน: รุ่นที่ 1
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
หลัง: รุ่นที่ 2
const {onRequest} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");
// Define the secret parameter
const apiKey = defineSecret("API_KEY");
exports.getQuote = onRequest(
// make the secret available to this function
{ secrets: [apiKey] },
async (req, res) => {
// retrieve the value of the secret
const quote = await fetchMotivationalQuote(apiKey.value());
// ...
}
);
ตั้งค่าตัวเลือกรันไทม์
การกําหนดค่าตัวเลือกรันไทม์มีการเปลี่ยนแปลงระหว่างรุ่นที่ 1 กับรุ่นที่ 2 นอกจากนี้ รุ่นที่ 2 ยังเพิ่มความสามารถใหม่ในการตั้งค่าตัวเลือกสําหรับฟังก์ชันทั้งหมด
ก่อน: รุ่นที่ 1
const functions = require("firebase-functions/v1");
exports.date = functions
.runWith({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
})
// locate function closest to users
.region("asia-northeast1")
.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions
// locate function closest to users and database
.region("asia-northeast1")
.firestore.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
หลัง: รุ่นที่ 2
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions/v2");
// locate all functions closest to users
setGlobalOptions({ region: "asia-northeast1" });
exports.date = onRequest({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
ใช้การเกิดขึ้นพร้อมกัน
ข้อได้เปรียบที่สําคัญของฟังก์ชันรุ่นที่ 2 คือความสามารถของอินสแตนซ์ฟังก์ชันเดียวในการแสดงคําขอมากกว่า 1 รายการพร้อมกัน ซึ่งจะช่วยลดจํานวน Cold Start ที่ผู้ใช้ปลายทางพบได้อย่างมาก โดยค่าเริ่มต้น ระบบจะตั้งค่าการเรียกใช้พร้อมกันไว้ที่ 80 แต่คุณตั้งค่าเป็นค่าใดก็ได้ตั้งแต่ 1 ถึง 1,000
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
การปรับแต่งการทำงานพร้อมกันจะช่วยปรับปรุงประสิทธิภาพและลดต้นทุนของฟังก์ชัน ดูข้อมูลเพิ่มเติมเกี่ยวกับการทำงานพร้อมกันในอนุญาตคำขอพร้อมกัน
ตรวจสอบการใช้ตัวแปรส่วนกลาง
ฟังก์ชันรุ่นที่ 1 ที่เขียนขึ้นโดยไม่คำนึงถึงการทำงานพร้อมกันอาจใช้ตัวแปรส่วนกลางซึ่งตั้งค่าและอ่านในคำขอแต่ละรายการ เมื่อเปิดใช้การทำงานพร้อมกันและอินสแตนซ์เดียวเริ่มจัดการคำขอหลายรายการพร้อมกัน การดำเนินการนี้อาจทำให้เกิดข้อบกพร่องในฟังก์ชัน เนื่องจากคำขอที่ทำงานพร้อมกันจะเริ่มตั้งค่าและอ่านตัวแปรส่วนกลางพร้อมกัน
ขณะอัปเกรด คุณสามารถตั้งค่า CPU ของฟังก์ชันเป็น gcf_gen1
และตั้งค่า concurrency
เป็น 1 เพื่อคืนค่าลักษณะการทํางานของรุ่นที่ 1 ดังนี้
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
อย่างไรก็ตาม เราไม่แนะนําให้ใช้วิธีนี้เป็นการแก้ไขระยะยาว เนื่องจากจะเสียเปรียบด้านประสิทธิภาพของฟังก์ชันรุ่นที่ 2 แต่ให้ตรวจสอบการใช้ตัวแปรส่วนกลางในฟังก์ชันแทน และนําการตั้งค่าชั่วคราวเหล่านี้ออกเมื่อคุณพร้อม
ย้ายข้อมูลการเข้าชมไปยังฟังก์ชันรุ่นที่ 2 ใหม่
เช่นเดียวกับเมื่อเปลี่ยนภูมิภาคหรือประเภททริกเกอร์ของฟังก์ชัน คุณจะต้องตั้งชื่อใหม่ให้ฟังก์ชันรุ่นที่ 2 และย้ายข้อมูลการเข้าชมไปยังฟังก์ชันดังกล่าวอย่างช้าๆ
คุณจะอัปเกรดฟังก์ชันจากรุ่นที่ 1 เป็นรุ่นที่ 2 ที่มีชื่อเดียวกันและเรียกใช้ firebase deploy
ไม่ได้ เนื่องจากจะทำให้เกิดข้อผิดพลาดต่อไปนี้
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
ก่อนทำตามขั้นตอนเหล่านี้ โปรดตรวจสอบว่าฟังก์ชันทำงานแบบไม่เปลี่ยนแปลง เนื่องจากทั้งฟังก์ชันเวอร์ชันใหม่และเวอร์ชันเก่าจะทํางานพร้อมกันในระหว่างการเปลี่ยนแปลง เช่น หากคุณมีฟังก์ชันรุ่นที่ 1 ที่ตอบสนองต่อเหตุการณ์การเขียนใน Firestore ให้ตรวจสอบว่าการตอบสนองการเขียน 2 ครั้ง โดย 1 ครั้งจากฟังก์ชันรุ่นที่ 1 และอีก 1 ครั้งจากฟังก์ชันรุ่นที่ 2 ในการตอบสนองต่อเหตุการณ์เหล่านั้นทำให้แอปอยู่ในสถานะที่สอดคล้องกัน
- เปลี่ยนชื่อฟังก์ชันในโค้ดฟังก์ชัน เช่น เปลี่ยนชื่อ
resizeImage
เป็นresizeImageSecondGen
- ติดตั้งใช้งานฟังก์ชันเพื่อให้ทั้งฟังก์ชันรุ่นที่ 1 เดิมและฟังก์ชันรุ่นที่ 2 ทํางานอยู่
- ในกรณีของทริกเกอร์ที่เรียกได้ คิวงาน และ HTTP ให้เริ่มชี้ไคลเอ็นต์ทั้งหมดไปยังฟังก์ชันรุ่นที่ 2 โดยอัปเดตโค้ดไคลเอ็นต์ด้วยชื่อหรือ URL ของฟังก์ชันรุ่นที่ 2
- เมื่อใช้ทริกเกอร์เบื้องหลัง ทั้งฟังก์ชันรุ่นที่ 1 และรุ่นที่ 2 จะตอบสนองต่อทุกเหตุการณ์ทันทีที่ติดตั้งใช้งาน
- เมื่อย้ายข้อมูลการเข้าชมทั้งหมดแล้ว ให้ลบฟังก์ชันรุ่นที่ 1 โดยใช้คําสั่ง
firebase functions:delete
ของ Firebase CLI- (ไม่บังคับ) เปลี่ยนชื่อฟังก์ชันรุ่นที่ 2 ให้ตรงกับชื่อของฟังก์ชันรุ่นที่ 1