1. nesil işlevleri kullanan uygulamalar, bu kılavuzdaki talimatları kullanarak 2. nesle geçiş yapmalıdır. 2. nesil işlevler, daha iyi performans, daha iyi yapılandırma, daha iyi izleme ve daha fazlasını sunmak için Cloud Run kullanır.
Bu belgedeki örneklerde, CommonJS modülleri (require tarzı içe aktarmalar) ile JavaScript kullandığınız varsayılmaktadır ancak aynı ilkeler ESM (import … from tarzı içe aktarmalar) ve TypeScript ile JavaScript için de geçerlidir.
Taşıma süreci
1. nesil ve 2. nesil işlevler aynı kaynak dosyasında yan yana bulunabilir. Bu sayede, kod tabanınızı hazır olduğunuzda parça parça taşıyabilirsiniz. Ancak paketlerin bu şekilde karıştırılması tek bir ayrı işlev içinde çalışmaz.
İşlevleri tek tek taşımanızı, devam etmeden önce test ve doğrulama yapmanızı öneririz.
Firebase CLI ve firebase-functions sürümlerini doğrulama
En az Firebase CLI sürümü 12.00 ve firebase-functions sürümü 4.3.0 kullandığınızdan emin olun. Daha yeni sürümler, 1. neslin yanı sıra 2. nesli de destekler.
İçe aktarma işlemlerini güncelleme
2. nesil işlevler, firebase-functions SDK'sındaki v2 alt paketinden içe aktarılır. Firebase CLI'nın, işlev kodunuzu 1. nesil mi yoksa 2. nesil işlev olarak mı dağıtacağını belirlemesi için bu farklı içe aktarma yolu yeterlidir.
v2 alt paketi modülerdir ve yalnızca ihtiyacınız olan modülü içe aktarmanızı öneririz.
Önce: 1. nesil
const functions = require("firebase-functions/v1");
Sonra: 2. nesil
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
Tetikleyici tanımlarını güncelleme
2. nesil SDK, modüler içe aktarmaları tercih ettiğinden tetikleyici tanımlarını önceki adımda değiştirilen içe aktarmaları yansıtacak şekilde güncelleyin.
Bazı tetikleyiciler için geri çağırmalara iletilen bağımsız değişkenler değişti. Bu örnekte, onDocumentCreated geri çağırma işlevinin bağımsız değişkenlerinin tek bir event nesnesinde birleştirildiğini görebilirsiniz. Ayrıca, bazı tetikleyicilerde onRequest tetikleyicisinin cors seçeneği gibi kullanışlı yeni yapılandırma özellikleri bulunur.
Önce: 1. nesil
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
Sonra: 2. nesil
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) => {
/* ... */
});
JavaScript'te yeniden yapılandırma ile yeniden yazma çalışmalarını en aza indirme
İşlevlerinizde büyük ölçüde 1. nesil bağlama veya sağlayıcıya özel parametrelere (message ya da snapshot gibi) dayalı karmaşık gövdeler varsa 2. nesil SDK'da yerleşik olarak bulunan 1. nesil uyumluluk yardımcılarını kullanabilirsiniz.
2. nesil SDK, etkinlik nesnesini 1. nesil imzalarla eşleşen alıcılarla otomatik olarak yamalar. Bu sayede, JavaScript'in yapı sökme özelliğini kullanarak bu özellikleri doğrudan işleyici imzasında ayıklayabilir ve işlev mantığınızı yeniden yazma ihtiyacını en aza indirebilirsiniz.
Sağlayıcı eşleme referansı
| Sağlayıcı | 1. nesil bağımsız değişkenler | 2. nesil yamalı etkinlik yapı sökümü |
| Pub/Sub | (message, context)
|
({ message, context }) => { ... }
|
| Cloud Firestore | (snapshot, context)
|
({ snapshot, context }) => { ... }
|
| Cloud Storage | (object, context)
|
({ object, context }) => { ... }
|
| Realtime Database | (snapshot, context)
|
({ snapshot, context }) => { ... }
|
| Remote Config | (version, context)
|
({ version, context }) => { ... }
|
| Cloud Scheduler | (context)
|
({ context }) => { ... }
|
| Görev Sırası | (data, context)
|
({ data, context }) => { ... }
|
Önceki (1. nesil):
export const myPubSubV1 = functions.pubsub.topic("my-topic").onPublish((message, context) => {
const data = message.json;
const eventId = context.eventId;
// ... rest of the logic
});
Yeni Alternatif (Yapıbozum ile 2. nesil):
import { onMessagePublished } from "firebase-functions/v2/pubsub";
export const myPubSubV2 = onMessagePublished("my-topic", ({ message, context }) => {
// No need to change the function body!
const data = message.json; // Uses v1 Message wrapper
const eventId = context.eventId; // Uses v1 EventContext map
// ... rest of the logic
});
Parametreli yapılandırmayı kullanma
2. nesil işlevler, kod tabanınızda yapılandırma parametrelerini bildirimli olarak tanımlamak için daha güvenli bir arayüz sunarak functions.config desteğini sonlandırır.
Yeni params modülü sayesinde CLI, tüm parametreler geçerli bir değere sahip olmadığı sürece dağıtımı engeller. Böylece, işlevlerin eksik yapılandırmayla dağıtılması önlenir.
Önce: 1. nesil
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
Sonra: 2. nesil
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());
// ...
}
);
functions.config ile mevcut bir ortam yapılandırmanız varsa 2. nesle yükseltme işleminizin bir parçası olarak bu yapılandırmayı taşıyın.
functions.config API'nin desteği sonlandırıldı ve Mart 2027'de kullanımdan kaldırılacak.
Bu tarihten sonra functions.config ile yapılan dağıtımlar başarısız olacak.
Dağıtım hatalarını önlemek için Firebase KSA'yı kullanarak yapılandırmanızı Cloud Secret Manager'a taşıyın. Yapılandırmanızı taşımanın en verimli ve güvenli yolu olarak bu yöntem kesinlikle önerilir.
Firebase CLI ile yapılandırmayı dışa aktarma
Mevcut ortam yapılandırmanızı Cloud Secret Manager'da yeni bir gizli anahtara aktarmak için
config exportkomutunu kullanın:$ 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```Gizli anahtarları bağlamak için işlev kodunu güncelleme
Cloud Secret Manager'daki yeni gizli anahtarda depolanan yapılandırmayı kullanmak için işlev kaynağınızda
defineJsonSecretAPI'sini kullanın. Ayrıca gizli anahtarların, ihtiyaç duyan tüm işlevlere bağlı olduğundan emin olun.Önce
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });Sonra
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; // ... });Functions Dağıtma
Değişiklikleri uygulamak ve gizli anahtar izinlerini bağlamak için güncellenmiş işlevlerinizi dağıtın.
firebase deploy --only functions:<your-function-name>
Çalışma zamanı seçeneklerini ayarlama
Çalışma zamanı seçeneklerinin yapılandırması 1. ve 2. nesil arasında değişti. 2. nesil, tüm işlevler için seçenekleri ayarlama konusunda yeni bir özellik de ekler.
Önce: 1. nesil
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) => {
// ...
});
Sonra: 2. nesil
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) => {
/* ... */
});
Varsayılan hizmet hesabını güncelleme (isteğe bağlı)
1. nesil işlevler, Firebase API'lerine erişim yetkisi vermek için Google App Engine varsayılan hizmet hesabını kullanırken 2. nesil işlevler Compute Engine varsayılan hizmet hesabını kullanır. Bu fark, 1. nesil hizmet hesabına özel izinler verdiğiniz durumlarda 2. nesle taşınan işlevler için izin sorunlarına yol açabilir. Hizmet hesabı izinlerini değiştirmediyseniz bu adımı atlayabilirsiniz.
Önerilen çözüm, mevcut 1. nesil App Engine varsayılan hizmet hesabını 2. nesle taşımak istediğiniz işlevlere açıkça atayarak 2. nesil varsayılan hizmet hesabını geçersiz kılmaktır. Bunu yapmak için taşınan her işlevin serviceAccountEmail için doğru değeri ayarladığından emin olun:
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) => {
// ...
});
Alternatif olarak, hizmet hesabı ayrıntılarını hem App Engine varsayılan hizmet hesabındaki (1. nesil için) hem de Compute Engine varsayılan hizmet hesabındaki (2. nesil için) gerekli tüm izinlerle eşleşecek şekilde değiştirebilirsiniz.
Eşzamanlılığı kullanma
2. nesil işlevlerin önemli bir avantajı, tek bir işlev örneğinin aynı anda birden fazla isteği sunabilmesidir. Bu sayede, son kullanıcıların yaşadığı yeni başlatma sayısını önemli ölçüde azaltabilirsiniz. Eşzamanlılık varsayılan olarak 80'e ayarlıdır ancak 1 ile 1.000 arasında herhangi bir değere ayarlayabilirsiniz:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
Eşzamanlılığı ayarlamak, performansı artırabilir ve işlevlerin maliyetini azaltabilir. Eşzamanlı isteklere izin ver bölümünde eşzamanlılık hakkında daha fazla bilgi edinin.
Genel değişken kullanımını denetleme
Eşzamanlılık dikkate alınmadan yazılan 1. nesil işlevler, her istekte ayarlanan ve okunan global değişkenleri kullanabilir. Eşzamanlılık etkinleştirildiğinde ve tek bir örnek aynı anda birden fazla isteği işlemeye başladığında, eşzamanlı istekler global değişkenleri aynı anda ayarlamaya ve okumaya başladığı için işlevinizde hatalar oluşabilir.
Yükseltme sırasında, işlevinizin CPU'sunu gcf_gen1, concurrency değerini ise 1 olarak ayarlayarak 1. nesil davranışını geri yükleyebilirsiniz:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
Ancak bu, 2. nesil işlevlerin performans avantajlarından vazgeçtiği için uzun vadeli bir çözüm olarak önerilmez. Bunun yerine, işlevlerinizdeki global değişkenlerin kullanımını denetleyin ve hazır olduğunuzda bu geçici ayarları kaldırın.
Trafiği yeni 2. nesil işlevlere taşıma
Bir işlevin bölgesini veya tetikleyici türünü değiştirirken olduğu gibi, 2. nesil işleve yeni bir ad vermeniz ve trafiği yavaşça bu işleve taşımanız gerekir.
Bir işlevi aynı adla 1. nesilden 2. nesle yükseltip firebase deploy komutunu çalıştırmak mümkün değildir. Aksi takdirde şu hata oluşur:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Taşıma stratejisi, işlevinizin kullandığı tetikleyici türüne bağlıdır.
Çağrılabilir, görev sırası ve HTTP tetikleyicilerini taşıma
Bu tetikleyiciler doğrudan çağrılardır. 2. nesil işlevin yeni bir adı (ve HTTP tetikleyicileri için yeni bir URL'si) olacağından istemcileri güncelleyerek trafiği taşıyabilirsiniz.
- Kodunuzdaki işlevi yeniden adlandırın (örneğin,
myCallableişlevinimyCallableV2olarak yeniden adlandırın). - İşlevi dağıtın. Artık hem 1. nesil hem de 2. nesil işlevler çalışıyor.
- İstemci kodunuzu veya çağrıyı yeni 2. nesil işlevin adını ya da URL'sini gösterecek şekilde güncelleyin.
- Tüm trafik yeni işleve kaydırıldıktan sonra Firebase CLI'nın
firebase functions:deletekomutunu kullanarak 1. nesil işlevi silin.
Arka plan tetikleyicilerini taşıma
Arka plan tetikleyicileri (Pub/Sub, Cloud Firestore ve Cloud Storage tetikleyicileri gibi), projenizdeki etkinliklere yanıt verir. Geçiş sırasında hiçbir etkinliği kaçırmamak için geçici olarak hem 1. nesil hem de 2. nesil işlevleri yan yana çalıştırmanız gerekir.
Geçiş döneminde her iki işlev de aynı etkinlikte tetiklenir. Bu, işletme mantığınızın etkinlik başına iki kez çalıştırılacağı anlamına gelir. Devam etmeden önce işlevinizin idempotent olduğundan emin olun.
Mevcut 1. nesil işlevi kodunuzda tutarak 2. nesil işlevi 1. nesil işlevle birlikte ekleyin ve aynı etkinlik kaynağını dinleyen 2. nesil işlevi ekleyin.
import * as functions from "firebase-functions/v1"; import { onMessagePublished } from "firebase-functions/v2/pubsub"; // --- Existing 1st gen function --- export const myPubSub = functions.pubsub.topic("my-topic").onPublish((message, context) => { console.log("V1 handler running for event:", context.eventId); // ... existing v1 function logic ... }); // --- New v2 passthrough function --- export const myPubSubV2 = onMessagePublished("my-topic", async ({ message, context }) => { console.log("v2 handler triggering V1 for event:", context.eventId); // Call the v1 function's handler await myPubSub.run(message, context); });firebase deploykomutunu çalıştırın. Artık her iki işlev de etkin ve aynı etkinlikleri dinliyor.2. nesil işlevin trafik aldığını doğrulayın. Her iki işlevin günlüklerini izleyin. 2. nesil işlevin tüm etkinlikler için çağrıldığından ve çağrıların başarılı olduğundan emin olun.
İşlevin doğru şekilde çalıştığından emin olduktan sonra asıl iş mantığını 1. nesil işlevden 2. nesil işlevin gövdesine taşıyın. Doğrudan iletme yöntemini kullandıysanız
myPubSub.run()çağrısını kaldırın.import * as functions from "firebase-functions/v1"; import { onMessagePublished } from "firebase-functions/v2/pubsub"; // --- Existing v1 function (to be removed next) --- export const myPubSub = functions.pubsub.topic("my-topic").onPublish((message, context) => { console.log("v1 handler running for event:", context.eventId); // ... existing v1 function logic ... }); // --- New v2 function with full logic --- export const myPubSubV2 = onMessagePublished("my-topic", ({ message, context }) => { console.log("v2 handler running for event:", context.eventId); // ... existing v1 function logic WAS MOVED HERE ... });Bu değişikliği dağıtın.
1. nesil işlev tanımını kodunuzdan kaldırın ve yeniden dağıtın. CLI, 1. nesil işlevi Google Cloud konumundan silmenizi ister.