Le app che utilizzano funzioni di 1ª gen. devono valutare la migrazione alla 2ª gen. seguendo le istruzioni riportate in questa guida. Le funzioni di 2ª gen. utilizzano Cloud Run per offrire prestazioni, configurazione e monitoraggio migliori e altro ancora.
Gli esempi in questa pagina presuppongono che tu stia utilizzando JavaScript con i moduli CommonJS
(importazioni in stile require), ma gli stessi principi si applicano a JavaScript con ESM
(importazioni in stile import … from) e TypeScript.
Il processo di migrazione
Le funzioni di 1ª gen. e 2ª gen. possono coesistere nello stesso file. Ciò consente una facile migrazione passo passo, quando sei pronto. Ti consigliamo di eseguire la migrazione di una funzione alla volta, eseguendo test e verifiche prima di procedere.
Verificare le versioni di Firebase CLI e firebase-functions
Assicurati di utilizzare almeno la versione 12.00 di Firebase CLI e
firebase-functions la versione 4.3.0. Qualsiasi versione più recente supporterà sia la 2ª gen. sia la 1ª gen.
Aggiornare le importazioni
Le funzioni di 2ª gen. importano dal v2 sottocomponente nell'firebase-functions SDK.
Questo percorso di importazione diverso è tutto ciò di cui Firebase CLI ha bisogno per determinare se
eseguire il deployment del codice della funzione come funzione di 1ª o 2ª gen.
Il sottocomponente v2 è modulare e ti consigliamo di importare solo il modulo specifico
di cui hai bisogno.
Prima: 1ª gen.
const functions = require("firebase-functions/v1");
Dopo: 2ª gen.
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
Aggiornare le definizioni dei trigger
Poiché l'SDK di 2ª gen. favorisce le importazioni modulari, aggiorna le definizioni dei trigger in modo che riflettano le importazioni modificate del passaggio precedente.
Gli argomenti passati ai callback per alcuni trigger sono cambiati. In questo
esempio, tieni presente che gli argomenti del callback onDocumentCreated sono stati
consolidati in un singolo oggetto event. Inoltre, alcuni trigger hanno
nuove funzionalità di configurazione pratiche, come l'opzione cors
del trigger onRequest.
Prima: 1ª gen.
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
Dopo: 2ª gen.
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) => {
/* ... */
});
Utilizzare la configurazione con parametri
Le funzioni di 2ª gen. non supportano più functions.config a favore di un'interfaccia più sicura
per la definizione dichiarativa dei parametri di configurazione
all'interno del codebase.
Con il nuovo modulo params, l'interfaccia a riga di comando blocca il deployment a meno che tutti i parametri
non abbiano un valore valido, assicurando che una funzione non venga sottoposta a deployment con una configurazione
mancante.
Prima: 1ª gen.
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
Dopo: 2ª gen.
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());
// ...
}
);
Se hai una configurazione dell'ambiente esistente con functions.config, esegui la migrazione
di questa configurazione nell'ambito dell'upgrade alla 2ª gen.
L'API functions.config è obsoleta e verrà ritirata a marzo 2027.
Dopo questa data, i deployment con functions.config non andranno a buon fine.
Per evitare errori di deployment, esegui la migrazione della configurazione a Cloud Secret Manager utilizzando Firebase CLI. Questa è la soluzione più efficiente e sicura per eseguire la migrazione della configurazione.
Esportare la configurazione con la CLI Firebase
Utilizza il comando
config exportper esportare la configurazione dell'ambiente esistente in un nuovo secret in 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```Aggiornare il codice della funzione per associare i secret
Per utilizzare la configurazione archiviata nel nuovo secret in Cloud Secret Manager, utilizza l'API
defineJsonSecretnel codice sorgente della funzione. Inoltre, assicurati che i secret siano associati a tutte le funzioni che ne hanno bisogno.Prima
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });Dopo
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; // ... });Eseguire il deployment delle funzioni
Esegui il deployment delle funzioni aggiornate per applicare le modifiche e associare le autorizzazioni dei secret.
firebase deploy --only functions:<your-function-name>
Impostare le opzioni di runtime
La configurazione delle opzioni di runtime è cambiata tra la 1ª e la 2ª gen. La 2ª gen. aggiunge anche una nuova funzionalità per impostare le opzioni per tutte le funzioni.
Prima: 1ª gen.
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) => {
// ...
});
Dopo: 2ª gen.
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) => {
/* ... */
});
(Facoltativo) Aggiornare il service account predefinito
Mentre le funzioni di 1ª gen. utilizzano il service account predefinito di App Engine per autorizzare l'accesso alle API Firebase, le funzioni di 2ª gen. utilizzano il service account predefinito di Compute Engine . Questa differenza può causare problemi di autorizzazioni per le funzioni di cui è stata eseguita la migrazione alla 2ª gen. nei casi in cui hai concesso autorizzazioni speciali al service account di 1ª gen. Se non hai modificato le autorizzazioni del service account, puoi saltare questo passaggio.
La soluzione consigliata è assegnare esplicitamente il service account predefinito di App Engine di 1ª gen. esistente alle funzioni di cui vuoi eseguire la migrazione alla 2ª gen., sostituendo il valore predefinito di 2ª gen. Per farlo, assicurati che ogni funzione di cui è stata eseguita la migrazione imposti il valore corretto per 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) => {
// ...
});
In alternativa, puoi assicurarti di modificare i dettagli del service account in modo che corrispondano a tutte le autorizzazioni necessarie sia per il service account predefinito di App Engine (per la 1ª gen.) sia per il service account predefinito di Compute Engine (per la 2ª gen.).
Utilizzare la concorrenza
Un vantaggio significativo delle funzioni di 2ª gen. è la capacità di una singola istanza di funzione di gestire più richieste contemporaneamente. Ciò può ridurre drasticamente il numero di avvii a freddo riscontrati dagli utenti finali. Per impostazione predefinita, la concorrenza è impostata su 80, ma puoi impostarla su qualsiasi valore compreso tra 1 e 1000:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
La regolazione della concorrenza può migliorare le prestazioni e ridurre il costo delle funzioni. Scopri di più sulla concorrenza in Consentire le richieste simultanee.
Controllare l'utilizzo delle variabili globali
Le funzioni di 1ª gen. scritte senza tenere conto della concorrenza potrebbero utilizzare variabili globali impostate e lette su ogni richiesta. Quando la concorrenza è abilitata e una singola istanza inizia a gestire più richieste contemporaneamente, potrebbero essere introdotti bug nella funzione, poiché le richieste simultanee iniziano a impostare e leggere le variabili globali contemporaneamente.
Durante l'upgrade, puoi impostare la CPU della funzione su gcf_gen1 e impostare concurrency
su 1 per ripristinare il comportamento di 1ª gen.:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
Tuttavia, questa soluzione non è consigliata a lungo termine, in quanto rinuncia ai vantaggi in termini di prestazioni delle funzioni di 2ª gen. Controlla invece l'utilizzo delle variabili globali nelle funzioni e rimuovi queste impostazioni temporanee quando sei pronto.
Eseguire la migrazione del traffico alle nuove funzioni di 2ª gen.
Come quando modifichi la regione o il tipo di trigger di una funzione, dovrai assegnare un nuovo nome alla funzione di 2ª gen. ed eseguire lentamente la migrazione del traffico.
Non è possibile eseguire l'upgrade di una funzione dalla 1ª alla 2ª gen. con lo stesso nome
ed eseguire firebase deploy. In questo caso, verrà visualizzato il seguente errore:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Prima di seguire questi passaggi, assicurati che la funzione sia idempotente, poiché sia la nuova versione sia quella precedente della funzione verranno eseguite contemporaneamente durante la modifica. Ad esempio, se hai una funzione di 1ª gen. che risponde agli eventi di scrittura in Firestore, assicurati che la risposta a una scrittura due volte, una volta dalla funzione di 1ª gen. e una volta dalla funzione di 2ª gen., in risposta a questi eventi lasci l'app in uno stato coerente.
- Rinomina la funzione nel codice delle funzioni. Ad esempio, rinomina
resizeImageinresizeImageSecondGen. - Esegui il deployment della funzione, in modo che siano in esecuzione sia la funzione di 1ª gen. originale sia quella di 2ª gen.
- Nel caso di trigger chiamabili, di Task Queue e HTTP, inizia a indirizzare tutti i client alla funzione di 2ª gen. aggiornando il codice client con il nome o l'URL della funzione di 2ª gen.
- Con i trigger in background, le funzioni di 1ª e 2ª gen. risponderanno a ogni evento immediatamente dopo il deployment.
- Quando tutto il traffico è stato migrato, elimina la funzione di 1ª gen. utilizzando il comando
firebase functions:deletedi Firebase CLI.- (Facoltativo) Rinomina la funzione di 2ª gen. in modo che corrisponda al nome della funzione di 1ª gen.