Skip to content

Commit 8c934c9

Browse files
authored
feat: add firebase-app-hosting preset (#2864)
1 parent 536d79b commit 8c934c9

File tree

9 files changed

+174
-40
lines changed

9 files changed

+174
-40
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ staticwebapp.config.json
7171
.eslintcache
7272
playground/firebase.json
7373
.zeabur
74+
.apphosting
7475

7576
test/fixture/functions
7677
.data

docs/2.deploy/0.index.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ When deploying to production using CI/CD, Nitro tries to automatically detect th
2222
- [aws amplify](/deploy/providers/aws-amplify)
2323
- [azure](/deploy/providers/azure)
2424
- [cloudflare pages](/deploy/providers/cloudflare#cloudflare-pages)
25+
- [firebase app hosting](/deploy/providers/firebase#firebase-app-hosting-beta)
2526
- [netlify](/deploy/providers/netlify)
2627
- [stormkit](/deploy/providers/stormkit)
2728
- [vercel](/deploy/providers/vercel)

docs/2.deploy/20.providers/firebase.md

+53-21
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,58 @@
11
# Firebase
22

3-
> Deploy Nitro apps to Firebase.
3+
> Deploy Nitro apps to Firebase hosting.
44
5-
**Preset:** `firebase`
5+
::note
6+
You will need to be on the [**Blaze plan**](https://firebase.google.com/pricing) (Pay as you go) to get started.
7+
::
68

7-
:read-more{title="Firebase Hosting" to="https://firebase.google.com/docs/hosting"}
9+
<!--
810
9-
::note
10-
You need to be on the **Blaze plan** to use Nitro with cloud functions.
11+
## Firebase app hosting <sup>(beta)</sup>
12+
13+
Preset: `firebase_app_hosting`
14+
15+
:read-more{title="Firebase App Hosting" to="https://firebase.google.com/docs/app-hosting"}
16+
17+
::important
18+
Firebase app hosting support is currently available in the Nitro [nightly release channel](/guide/nightly).
1119
::
1220
21+
::tip
22+
You can integrate with this provider using [zero configuration](/deploy/#zero-config-providers).
23+
::
24+
25+
### Project setup
26+
27+
1. Go to the Firebase [console](https://console.firebase.google.com/) and set up a new project.
28+
2. Select **Build > App Hosting** from the sidebar.
29+
- You may need to upgrade your billing plan at this step.
30+
3. Click **Get Started**.
31+
- Choose a region.
32+
- Import a GitHub repository (you’ll need to link your GitHub account).
33+
- Configure deployment settings (project root directory and branch), and enable automatic rollouts.
34+
- Choose a unique ID for deployment.
35+
4. Wait for the first release to complete.
36+
37+
-->
38+
39+
## Firebase hosting
40+
41+
**Preset:** `firebase`
42+
43+
:read-more{title="Firebase Hosting" to="https://firebase.google.com/docs/hosting"}
44+
1345
::important
1446
This preset will deploy to firebase functions 1st gen by default. If you want to deploy to firebase functions 2nd gen, see the [instructions below](#using-2nd-generation-firebase-functions).
1547
::
1648

17-
## Project Setup
49+
### Project Setup
1850

19-
### Using firebase CLI (recommended)
51+
#### Using firebase CLI (recommended)
2052

2153
You may instead prefer to set up your project with the Firebase CLI, which will fetch your project ID for you, add required dependencies (see above) and even set up automated deployments via GitHub Actions (for hosting only). [Learn about installing the firebase CLI](https://firebase.google.com/docs/cli#windows-npm).
2254

23-
#### 1. Install firebase CLI globally
55+
1. Install firebase CLI globally
2456

2557
Always try to use the latest version of the Firebase CLI.
2658

@@ -30,7 +62,7 @@ npm install -g firebase-tools@latest
3062

3163
**Note**: You need to be on [^11.18.0](https://github.com/firebase/firebase-tools/releases/tag/v11.18.0) to deploy a `nodejs18` function.
3264

33-
#### 2. Initialize your firebase project
65+
2. Initialize your firebase project
3466

3567
```bash
3668
firebase login
@@ -57,11 +89,11 @@ Once complete, add the following to your `firebase.json` to enable server render
5789

5890
You can find more details in the [Firebase documentation](https://firebase.google.com/docs/hosting/quickstart).
5991

60-
### Alternative method
92+
#### Alternative method
6193

6294
If you don't already have a `firebase.json` in your root directory, Nitro will create one the first time you run it. In this file, you will need to replace `<your_project_id>` with the ID of your Firebase project. This file should then be committed to the git.
6395

64-
#### 1. Create a `.firebaserc` file
96+
1. Create a `.firebaserc` file
6597

6698
It is recommended to create a `.firebaserc` file so you don't need to manually pass your project ID to your `firebase` commands (with `--project <your_project_id>`):
6799

@@ -75,19 +107,19 @@ It is recommended to create a `.firebaserc` file so you don't need to manually p
75107

76108
This file is usually generated when you initialize your project with the Firebase CLI. But if you don't have one, you can create it manually.
77109

78-
#### 2. Install firebase dependencies
110+
2. Install firebase dependencies
79111

80112
Then, add Firebase dependencies to your project:
81113

82114
:pm-install{name="firebase-admin firebase-functions firebase-functions-test" dev}
83115

84-
#### 3. Log into the firebase CLI
116+
3. Log into the firebase CLI
85117

86118
Make sure you are authenticated with the firebase cli. Run this command and follow the prompts:
87119

88120
:pm-x{command="firebase-tools login"}
89121

90-
## Local preview
122+
### Local preview
91123

92124
You can preview a local version of your site if you need to test things out without deploying.
93125

@@ -96,7 +128,7 @@ NITRO_PRESET=firebase npm run build
96128
firebase emulators:start
97129
```
98130

99-
## Build and deploy
131+
### Build and deploy
100132

101133
Deploy to Firebase Hosting by running a Nitro build and then running the `firebase deploy` command.
102134

@@ -112,7 +144,7 @@ If you installed the Firebase CLI globally, you can also run:
112144
firebase deploy
113145
```
114146

115-
## Using 2nd generation firebase functions
147+
### Using 2nd generation firebase functions
116148

117149
- [Comparison between 1st and 2nd generation functions](https://firebase.google.com/docs/functions/version-comparison)
118150

@@ -148,7 +180,7 @@ If you cannot use configuration for any reason, alternatively you can use `NITRO
148180

149181
If you already have a deployed version of your website and want to upgrade to 2nd gen, [see the Migration process on Firebase docs](https://firebase.google.com/docs/functions/2nd-gen-upgrade). Namely, the CLI will ask you to delete your existing functions before deploying the new ones.
150182

151-
## Options
183+
### Options
152184

153185
You can set options for the firebase functions in your `nitro.config.ts` file:
154186

@@ -184,7 +216,7 @@ export default defineNuxtConfig({
184216

185217
You can also set options for 1st generation Cloud Functions if the `gen` option is set to `1`. Note these are different from the options for 2nd generation Cloud Functions.
186218

187-
### Runtime Node.js version
219+
#### Runtime Node.js version
188220

189221
You can set custom Node.js version in configuration:
190222

@@ -225,17 +257,17 @@ You might also need to add a runtime key to your `firebase.json` file:
225257

226258
You can read more about this in [Firebase Docs](https://firebase.google.com/docs/functions/manage-functions?gen=2nd#set_nodejs_version).
227259

228-
## If your firebase project has other cloud functions
260+
### If your firebase project has other cloud functions
229261

230262
You may be warned that other cloud functions will be deleted when you deploy your nitro project. This is because nitro will deploy your entire project to firebase functions. If you want to deploy only your nitro project, you can use the `--only` flag:
231263

232264
```bash
233265
firebase deploy --only functions:server,hosting
234266
```
235267

236-
## Advanced
268+
### Advanced
237269

238-
### Renaming function
270+
#### Renaming function
239271

240272
When deploying multiple apps within the same Firebase project, you must give your server a unique name in order to avoid overwriting
241273
your functions.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
"semver": "^7.6.3",
157157
"serve-placeholder": "^2.0.2",
158158
"serve-static": "^1.16.2",
159-
"std-env": "^3.7.0",
159+
"std-env": "^3.8.0",
160160
"ufo": "^1.5.4",
161161
"uncrypto": "^0.1.3",
162162
"unctx": "^2.3.1",

pnpm-lock.yaml

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/presets/_types.gen.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ export interface PresetOptions {
2020

2121
export const presetsWithConfig = ["awsAmplify","awsLambda","azure","cloudflare","firebase","netlify","vercel"] as const;
2222

23-
export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure" | "azure-functions" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-module-legacy" | "cloudflare-pages" | "cloudflare-pages-static" | "cloudflare-worker" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgio" | "firebase" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis" | "iis-handler" | "iis-node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlify-edge" | "netlify-legacy" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-listener" | "node-server" | "platform-sh" | "render-com" | "service-worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static";
23+
export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure" | "azure-functions" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-module-legacy" | "cloudflare-pages" | "cloudflare-pages-static" | "cloudflare-worker" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgio" | "firebase" | "firebase-app-hosting" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis" | "iis-handler" | "iis-node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlify-edge" | "netlify-legacy" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-listener" | "node-server" | "platform-sh" | "render-com" | "service-worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static";
2424

25-
export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure" | "azure-functions" | "azureFunctions" | "azure_functions" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-module-legacy" | "cloudflareModuleLegacy" | "cloudflare_module_legacy" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "cloudflare-worker" | "cloudflareWorker" | "cloudflare_worker" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgio" | "firebase" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlifyBuilder" | "netlify_builder" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-legacy" | "netlifyLegacy" | "netlify_legacy" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-listener" | "nodeListener" | "node_listener" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "service-worker" | "serviceWorker" | "service_worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercelEdge" | "vercel_edge" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {});
25+
export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure" | "azure-functions" | "azureFunctions" | "azure_functions" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-module-legacy" | "cloudflareModuleLegacy" | "cloudflare_module_legacy" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "cloudflare-worker" | "cloudflareWorker" | "cloudflare_worker" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgio" | "firebase" | "firebase-app-hosting" | "firebaseAppHosting" | "firebase_app_hosting" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlifyBuilder" | "netlify_builder" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-legacy" | "netlifyLegacy" | "netlify_legacy" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-listener" | "nodeListener" | "node_listener" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "service-worker" | "serviceWorker" | "service_worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercelEdge" | "vercel_edge" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {});

src/presets/firebase/preset.ts

+47-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
import { defineNitroPreset } from "nitropack/kit";
2-
import { basename } from "pathe";
1+
import { defineNitroPreset, writeFile } from "nitropack/kit";
2+
import { version as nitroVersion } from "nitropack/meta";
3+
import { basename, join } from "pathe";
34
import type { Plugin } from "rollup";
45
import { genSafeVariableName } from "knitwork";
6+
import { stringifyYAML } from "confbox";
57
import { updatePackageJSON, writeFirebaseConfig } from "./utils";
8+
import type {
9+
AppHostingOptions,
10+
AppHostingOutputBundleConfig,
11+
FirebaseFunctionsOptions,
12+
} from "./types";
613

714
export type { FirebaseOptions as PresetOptions } from "./types";
815

@@ -23,7 +30,8 @@ const firebase = defineNitroPreset(
2330
await updatePackageJSON(nitro);
2431
},
2532
"rollup:before": (nitro, rollupConfig) => {
26-
const _gen = nitro.options.firebase?.gen as unknown;
33+
const _gen = (nitro.options.firebase as FirebaseFunctionsOptions)
34+
?.gen as unknown;
2735
if (!_gen || _gen === "default") {
2836
nitro.logger.warn(
2937
"Neither `firebase.gen` or `NITRO_FIREBASE_GEN` is set. Nitro will default to Cloud Functions 1st generation. It is recommended to set this to the latest generation (currently `2`). Set the version to remove this warning. See https://nitro.build/deploy/providers/firebase for more information."
@@ -34,7 +42,8 @@ const firebase = defineNitroPreset(
3442
nitro.options.appConfig.nitro = nitro.options.appConfig.nitro || {};
3543
nitro.options.appConfig.nitro.firebase = nitro.options.firebase;
3644

37-
const { serverFunctionName } = nitro.options.firebase;
45+
const { serverFunctionName } = nitro.options
46+
.firebase as FirebaseFunctionsOptions;
3847
if (
3948
serverFunctionName &&
4049
serverFunctionName !== genSafeVariableName(serverFunctionName)
@@ -68,4 +77,37 @@ const firebase = defineNitroPreset(
6877
}
6978
);
7079

71-
export default [firebase] as const;
80+
const firebaseAppHosting = defineNitroPreset(
81+
{
82+
extends: "node-server",
83+
serveStatic: true,
84+
hooks: {
85+
async compiled(nitro) {
86+
await writeFile(
87+
join(nitro.options.rootDir, ".apphosting/bundle.yaml"),
88+
stringifyYAML({
89+
version: "v1",
90+
runConfig: {
91+
runCommand: "node .output/server/index.mjs",
92+
...(nitro.options.firebase as AppHostingOptions)?.appHosting,
93+
},
94+
metadata: {
95+
framework: nitro.options.framework.name || "nitropack",
96+
frameworkVersion: nitro.options.framework.version || "2.x",
97+
adapterPackageName: "nitropack",
98+
adapterVersion: nitroVersion,
99+
},
100+
} satisfies AppHostingOutputBundleConfig),
101+
true
102+
);
103+
},
104+
},
105+
},
106+
{
107+
name: "firebase-app-hosting" as const,
108+
stdName: "firebase_app_hosting",
109+
url: import.meta.url,
110+
}
111+
);
112+
113+
export default [firebase, firebaseAppHosting] as const;

0 commit comments

Comments
 (0)