Aplikasi yang saat ini menggunakan fungsi generasi ke-1 harus mempertimbangkan migrasi ke generasi ke-2 menggunakan petunjuk dalam panduan ini. Fungsi generasi ke-2 menggunakan Cloud Run untuk memberikan performa yang lebih baik, konfigurasi yang lebih baik, pemantauan yang lebih baik, dan masih banyak lagi.
Contoh di halaman ini mengasumsikan bahwa Anda menggunakan JavaScript dengan modul CommonJS (impor gaya require
), tetapi prinsip yang sama berlaku untuk JavaScript dengan ESM (impor gaya import … from
) dan TypeScript.
Proses migrasi
Fungsi generasi ke-1 dan generasi ke-2 dapat berdampingan dalam file yang sama. Hal ini memungkinkan migrasi bertahap yang mudah, saat Anda siap. Sebaiknya migrasikan satu fungsi dalam satu waktu, lalu lakukan pengujian dan verifikasi sebelum melanjutkan.
Verifikasi Firebase CLI dan versi firebase-function
Pastikan Anda menggunakan setidaknya Firebase CLI versi 12.00
dan
firebase-functions
versi 4.3.0
. Versi yang lebih baru akan mendukung generasi ke-2
serta generasi ke-1.
Memperbarui impor
Fungsi generasi ke-2 diimpor dari subpaket v2
di firebase-functions
SDK.
Firebase CLI membutuhkan jalur impor yang berbeda untuk menentukan apakah
akan men-deploy kode fungsi Anda sebagai fungsi generasi ke-1 atau ke-2.
Subpaket v2
bersifat modular, dan sebaiknya hanya impor modul tertentu
yang Anda butuhkan.
Sebelum: generasi ke-1
const functions = require("firebase-functions");
Sesudah: generasi ke-2
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
Memperbarui definisi pemicu
Karena SDK generasi ke-2 mendukung impor modular, perbarui definisi pemicu untuk mencerminkan impor yang diubah dari langkah sebelumnya.
Argumen yang diteruskan ke callback untuk beberapa pemicu telah berubah. Dalam
contoh ini, perlu diperhatikan bahwa argumen ke callback onDocumentCreated
telah
digabungkan ke dalam satu objek event
. Selain itu, beberapa pemicu memiliki
fitur konfigurasi baru yang praktis, seperti opsi cors
pemicu onRequest
.
Sebelum: generasi ke-1
const functions = require("firebase-functions");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
Sesudah: generasi ke-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) => {
/* ... */
});
Menggunakan konfigurasi berparameter
Fungsi generasi ke-2 menghentikan dukungan untuk functions.config
dan mendukung antarmuka yang lebih aman untuk menentukan parameter konfigurasi secara deklaratif di dalam codebase Anda. Dengan modul params
baru, CLI akan memblokir deployment kecuali jika semua parameter memiliki nilai yang valid, sehingga memastikan bahwa fungsi tidak di-deploy jika tidak memiliki konfigurasi.
Bermigrasi ke subpaket params
Jika menggunakan konfigurasi lingkungan dengan functions.config
, Anda
dapat memigrasikan konfigurasi yang ada ke
konfigurasi berparameter.
Sebelum: generasi ke-1
const functions = require("firebase-functions");
exports.date = functions.https.onRequest((req, res) => {
const date = new Date();
const formattedDate =
date.toLocaleDateString(functions.config().dateformat);
// ...
});
Sesudah: generasi ke-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());
// ...
});
Menetapkan parameter value
Saat pertama kali melakukan deployment, Firebase CLI akan meminta semua nilai
parameter, dan menyimpan nilainya dalam file dotenv. Untuk mengekspor
nilai functions.config Anda, jalankan firebase functions:config:export
.
Untuk keamanan tambahan, Anda juga dapat menentukan jenis dan aturan validasi parameter.
Kasus khusus: Kunci API
Modul params
terintegrasi dengan Cloud Secret Manager, yang menyediakan
kontrol akses terperinci ke nilai sensitif seperti kunci API. Lihat
parameter secret
untuk mengetahui informasi selengkapnya.
Sebelum: generasi ke-1
const functions = require("firebase-functions");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
Sesudah: generasi ke-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());
// ...
}
);
Menetapkan opsi runtime
Konfigurasi opsi runtime telah berubah antara generasi ke-1 dan ke-2. Generasi ke-2 juga menambahkan kemampuan baru untuk menetapkan opsi untuk semua fungsi.
Sebelum: generasi ke-1
const functions = require("firebase-functions");
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) => {
// ...
});
Sesudah: generasi ke-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) => {
/* ... */
});
Gunakan permintaan serentak
Keuntungan signifikan dari fungsi generasi ke-2 adalah kemampuan instance fungsi tunggal untuk menayangkan lebih dari satu permintaan sekaligus. Hal ini dapat secara drastis mengurangi jumlah cold start yang dialami pengguna akhir. Secara default, permintaan serentak ditetapkan pada 80, tetapi Anda dapat menetapkannya ke nilai apa pun dari 1 hingga 1.000:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
Menyesuaikan permintaan serentak dapat meningkatkan performa dan mengurangi biaya fungsi. Pelajari lebih lanjut permintaan serentak di Mengizinkan permintaan serentak.
Mengaudit penggunaan variabel global
Fungsi generasi ke-1 yang ditulis tanpa mempertimbangkan konkurensi mungkin menggunakan variabel global yang ditetapkan dan dibaca pada setiap permintaan. Jika konkurensi diaktifkan dan satu instance mulai menangani beberapa permintaan sekaligus, hal ini dapat menimbulkan bug dalam fungsi Anda saat permintaan serentak mulai menetapkan dan membaca variabel global secara bersamaan.
Saat mengupgrade, Anda dapat menetapkan CPU fungsi ke gcf_gen1
dan menetapkan concurrency
ke 1 untuk memulihkan perilaku generasi ke-1:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
Namun, tindakan ini tidak direkomendasikan untuk perbaikan jangka panjang, karena menyebabkan performa dari fungsi generasi ke-2 terdampak secara negatif. Sebagai gantinya, lakukan audit terhadap penggunaan variabel global di fungsi Anda, dan hapus setelan sementara ini jika Anda sudah siap.
Memigrasikan traffic ke fungsi generasi ke-2 yang baru
Sama seperti saat mengubah region fungsi atau jenis pemicu, Anda harus memberi nama fungsi generasi ke-2 dan memigrasikan traffic ke sana secara perlahan.
Anda tidak dapat mengupgrade fungsi dari generasi ke-1 ke generasi ke-2 dengan nama yang sama dan menjalankan firebase deploy
. Tindakan tersebut akan menghasilkan error:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Sebelum mengikuti langkah-langkah ini, pastikan fungsi Anda idempoten, karena versi baru dan versi lama fungsi akan berjalan pada waktu yang sama selama perubahan. Misalnya, jika Anda memiliki fungsi generasi ke-1 yang merespons peristiwa operasi tulis di Firestore, pastikan merespons penulisan dua kali, sekali dengan fungsi generasi ke-1 dan sekali dengan fungsi generasi ke-2, sebagai respons terhadap peristiwa tersebut, keluar dari aplikasi Anda di status yang konsisten.
- Ganti nama fungsi di kode fungsi Anda. Misalnya, ganti nama
resizeImage
menjadiresizeImageSecondGen
. - Deploy fungsi, sehingga fungsi generasi ke-1 dan fungsi generasi ke-2 yang asli sedang berjalan.
- Dalam kasus pemicu callable, Task Queue, dan HTTP, mulai arahkan semua klien ke fungsi generasi ke-2 dengan memperbarui kode klien dengan nama atau URL fungsi generasi ke-2.
- Dengan pemicu latar belakang, fungsi generasi ke-1 dan generasi ke-2 akan langsung merespons setiap peristiwa setelah deployment.
- Saat semua traffic dimigrasikan, hapus fungsi generasi ke-1 menggunakan perintah
firebase functions:delete
firebase CLI.- ATau, ganti nama fungsi generasi ke-2 agar cocok dengan nama fungsi generasi ke-1.