From 408e564697efaba3021ee99098c8d83f4bb10cd2 Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Tue, 11 Aug 2026 12:37:56 -0700 Subject: [PATCH 1/3] fix(deploy): target Node 22 and the firebase-functions/v1 API in generated Cloud Functions The generated function declared engines.node 14, a runtime Cloud Functions decommissioned in early 2025, so it could not deploy at all. The gen 1 template also called functions.region() on the firebase-functions package root, which moved to the /v1 subpath in v6, so a deployed function crashed at cold start with TypeError: functions.region is not a function. Node 22 is the newest runtime Cloud Functions supports and satisfies the engines ranges of @angular/core and firebase-admin. Node 20 would deploy today, but its security support ended 2026-04-30. The same constant picks the Cloud Run base image, now node:22-slim. The docs example moves off the decommissioned functionsNodeVersion 12. --- docs/deploy/getting-started.md | 2 +- src/schematics/deploy/functions-templates.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/deploy/getting-started.md b/docs/deploy/getting-started.md index 5e3cf180d..1c701adc0 100644 --- a/docs/deploy/getting-started.md +++ b/docs/deploy/getting-started.md @@ -97,7 +97,7 @@ Setting `functionsNodeVersion` and `functionsRuntimeOptions` in your `angular.js "deploy": { "builder": "@angular/fire:deploy", "options": { - "functionsNodeVersion": 12, + "functionsNodeVersion": 22, "functionsRuntimeOptions": { "memory": "2GB", "timeoutSeconds": 10, diff --git a/src/schematics/deploy/functions-templates.ts b/src/schematics/deploy/functions-templates.ts index 13cd9ab14..772491049 100644 --- a/src/schematics/deploy/functions-templates.ts +++ b/src/schematics/deploy/functions-templates.ts @@ -1,6 +1,9 @@ import { DeployBuilderOptions } from './actions'; -export const DEFAULT_NODE_VERSION = 14; +// Must be a runtime Cloud Functions still accepts, and must satisfy the engines of @angular/core +// (the function runs the Angular server) and of firebase-admin. The `dockerfile` template below +// also drops it into `FROM node:-slim`, so it picks the base image on the Cloud Run path. +export const DEFAULT_NODE_VERSION = 22; export const DEFAULT_FUNCTION_NAME = 'ssr'; const DEFAULT_FUNCTION_REGION = 'us-central1'; @@ -34,7 +37,9 @@ export const defaultFunction = ( path: string, options: DeployBuilderOptions, functionName: string|undefined, -) => `const functions = require('firebase-functions'); +// `.region()` lives on the /v1 subpath since firebase-functions 6. Requiring the package root +// instead still resolves, and fails only when the deployed function serves its first request. +) => `const functions = require('firebase-functions/v1'); // Increase readability in Cloud Logging require("firebase-functions/logger/compat"); From 3b2902954dd441203422dbf440fe3e38691dfb40 Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Wed, 12 Aug 2026 12:13:51 -0700 Subject: [PATCH 2/3] docs(site): update the functionsNodeVersion example in the site copy The site/ copy of the deploy guide still showed the decommissioned 12, flagged in review. Also fixes a spelling error on the same passage. --- site/src/get-started/deploying.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/get-started/deploying.md b/site/src/get-started/deploying.md index b0e9011b4..f5c4886a7 100644 --- a/site/src/get-started/deploying.md +++ b/site/src/get-started/deploying.md @@ -98,13 +98,13 @@ To customize the deployment flow, you can use the configuration files you're alr ### Configuring Cloud Functions -Setting `functionsNodeVersion` and `functionsRuntimeOptions` in your `angular.json` allow you to custimze the version of Node.js Cloud Functions is running and run-time settings like timeout, VPC connectors, and memory. +Setting `functionsNodeVersion` and `functionsRuntimeOptions` in your `angular.json` allow you to customize the version of Node.js Cloud Functions is running and run-time settings like timeout, VPC connectors, and memory. ```json "deploy": { "builder": "@angular/fire:deploy", "options": { - "functionsNodeVersion": 12, + "functionsNodeVersion": 22, "functionsRuntimeOptions": { "memory": "2GB", "timeoutSeconds": 10, From bb6d1a1f277a6edcbab444f3a61cb5d7007b7738 Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Wed, 12 Aug 2026 12:14:01 -0700 Subject: [PATCH 3/3] test(deploy): assert the generated template's require path and runtime Add two specs for what the earlier commit in this PR fixed: the gen 1 template requires firebase-functions/v1, and the default runtime is 22. Both specs fail when run against the old template. Also moves the /v1 comment above the export so it no longer reads like a parameter annotation. --- .../deploy/functions-templates.jasmine.ts | 20 +++++++++++++++++++ src/schematics/deploy/functions-templates.ts | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 src/schematics/deploy/functions-templates.jasmine.ts diff --git a/src/schematics/deploy/functions-templates.jasmine.ts b/src/schematics/deploy/functions-templates.jasmine.ts new file mode 100644 index 000000000..b6bf4c148 --- /dev/null +++ b/src/schematics/deploy/functions-templates.jasmine.ts @@ -0,0 +1,20 @@ +import { DEFAULT_NODE_VERSION, defaultFunction, defaultPackage } from './functions-templates.js'; +import 'jasmine'; + +describe('functions templates', () => { + describe('defaultFunction', () => { + it('requires the firebase-functions/v1 subpath, where the v1 API lives on firebase-functions 6', () => { + const generated = defaultFunction('dist/app', {}, undefined); + expect(generated).toContain(`require('firebase-functions/v1')`); + expect(generated).not.toContain(`require('firebase-functions')`); + }); + }); + + describe('defaultPackage', () => { + it('defaults engines.node to a runtime Cloud Functions still accepts', () => { + const generated = defaultPackage({}, {}, {}); + expect(generated.engines.node).toBe(DEFAULT_NODE_VERSION.toString()); + expect(DEFAULT_NODE_VERSION).toBe(22); + }); + }); +}); diff --git a/src/schematics/deploy/functions-templates.ts b/src/schematics/deploy/functions-templates.ts index 772491049..b7af2a3b1 100644 --- a/src/schematics/deploy/functions-templates.ts +++ b/src/schematics/deploy/functions-templates.ts @@ -33,12 +33,12 @@ export const defaultPackage = ( private: true }); +// `.region()` lives on the /v1 subpath since firebase-functions 6. Requiring the package root +// instead still resolves, and fails only when the deployed function serves its first request. export const defaultFunction = ( path: string, options: DeployBuilderOptions, functionName: string|undefined, -// `.region()` lives on the /v1 subpath since firebase-functions 6. Requiring the package root -// instead still resolves, and fails only when the deployed function serves its first request. ) => `const functions = require('firebase-functions/v1'); // Increase readability in Cloud Logging