Aplikasi yang 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/v1");
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/v1");
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 guna 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.
Sebelum: generasi ke-1
const functions = require("firebase-functions/v1");
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());
// ...
}
);
Jika Anda memiliki konfigurasi lingkungan yang ada dengan functions.config, migrasikan
konfigurasi ini sebagai bagian dari upgrade ke generasi ke-2.
functions.config API yang tidak digunakan lagi akan dihentikan pada Maret 2027.
Setelah tanggal tersebut, deployment dengan functions.config akan gagal.
Untuk mencegah kegagalan deployment, migrasikan konfigurasi Anda ke Cloud Secret Manager menggunakan Firebase CLI. Cara ini sangat direkomendasikan karena merupakan cara paling efisien dan aman untuk memigrasikan konfigurasi Anda.
Konfigurasi ekspor dengan Firebase CLI
Gunakan perintah
config exportuntuk mengekspor konfigurasi lingkungan yang ada ke secret baru di Cloud Secret Manager:$ firebase functions:config:export i This command retrieves your Runtime Config values (accessed via functions.config()) and exports them as a Secret Manager secret. i Fetching your existing functions.config() from your project... ✔ Fetched your existing functions.config(). i Configuration to be exported: ⚠ This may contain sensitive data. Do not share this output. { ... } ✔ What would you like to name the new secret for your configuration? RUNTIME_CONFIG ✔ Created new secret version projects/project/secrets/RUNTIME_CONFIG/versions/1```Perbarui kode fungsi untuk mengikat secret
Untuk menggunakan konfigurasi yang disimpan di secret baru di Cloud Secret Manager, gunakan
defineJsonSecretAPI di sumber fungsi Anda. Selain itu, pastikan secret terikat ke semua fungsi yang memerlukannya.Sebelum
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });Setelah
const { onRequest } = require("firebase-functions/v2/https"); const { defineJsonSecret } = require("firebase-functions/params"); const config = defineJsonSecret("RUNTIME_CONFIG"); exports.myFunction = onRequest( // Bind secret to your function { secrets: [config] }, (req, res) => { // Access secret values via .value() const apiKey = config.value().someapi.key; // ... });Deploy Fungsi
Deploy fungsi yang telah diupdate untuk menerapkan perubahan dan mengikat izin secret.
firebase deploy --only functions:<your-function-name>
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/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) => {
// ...
});
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) => {
/* ... */
});
Memperbarui akun layanan default (opsional)
Meskipun fungsi generasi ke-1 menggunakan akun layanan default Google App Engine untuk mengizinkan akses ke Firebase API, fungsi generasi ke-2 menggunakan akun layanan default Compute Engine. Perbedaan ini dapat menyebabkan masalah izin untuk fungsi yang dimigrasikan ke generasi ke-2 jika Anda telah memberikan izin khusus ke akun layanan generasi ke-1. Jika belum mengubah izin akun layanan, Anda dapat melewati langkah ini.
Solusi yang direkomendasikan adalah menetapkan akun layanan default App Engine
generasi ke-1 yang ada secara eksplisit ke fungsi yang ingin Anda migrasikan ke generasi ke-2,
sehingga menggantikan default generasi ke-2. Anda dapat melakukannya dengan memastikan setiap fungsi
yang dimigrasikan menetapkan nilai yang benar untuk serviceAccountEmail:
const {onRequest} = require("firebase-functions/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions");
// Use the App Engine default service account for all functions
setGlobalOptions({serviceAccountEmail: '<my-project-number>@<wbr>appspot.gserviceaccount.com'});
// Now I use the App Engine default service account.
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
// I do too!
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
// ...
});
Atau, Anda dapat memastikan untuk mengubah detail akun layanan agar sesuai dengan semua izin yang diperlukan di akun layanan default App Engine (untuk Generasi ke-1) dan akun layanan default Compute Engine (untuk Generasi ke-2).
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 konkurensi dapat meningkatkan performa dan mengurangi biaya fungsi. Pelajari lebih lanjut konkurensi 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
resizeImagemenjadiresizeImageSecondGen. - 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:deletefirebase CLI.- ATau, ganti nama fungsi generasi ke-2 agar cocok dengan nama fungsi generasi ke-1.