Internal of Deploy Next.js on Firebase App Hosting

laiso
4 min readJun 8, 2024

--

The process for deploying Next.js on Firebase App Host has evolved. Initially, server-side rendering (SSR) was done through Cloud Functions, but with the introduction of second-generation Cloud Functions based on Cloud Run, deployments on Firebase using App Hosting now support Cloud the Run as well.

Tools and Command Roles

App Hosting also supports deployments via a GUI in the management console, allowing for user-friendly operations similar to Vercel.

Additionally, using the Firebase CLI command firebase apphosting:backends:create, you can create multiple backends.

The latest version of firebase-cli has added the following command:

❯ firebase --help | grep apphosting:

apphosting:backends:list [options] list Firebase App Hosting backends
apphosting:backends:create [options] create a Firebase App Hosting backend
apphosting:backends:get [options] <backend> print info about a Firebase App Hosting backend
apphosting:backends:delete [options] <backend> delete a Firebase App Hosting backend
apphosting:secrets:set [options] <secretName> create or update a secret for use in Firebase App Hosting
apphosting:secrets:grantaccess [options] <secretName> grant service accounts permissions to the provided secret
apphosting:secrets:describe <secretName> Get metadata for secret and its versions.
apphosting:secrets:access <secretName[@version]> Access secret value given secret and its version. Defaults to accessing the latest version.

Automatic Framework Detection and Build

firebase-framework-tools are responsible for the build process, which involves retrieving application source code from a GitHub repository, automatically detecting the framework, and deploying to Cloud Run.

https://github.com/FirebaseExtended/firebase-framework-tools

In this process, the presence of dependencies and configuration files are used to detect the framework, and a specialized build process is executed for each supported framework. For instance, @apphosting/adapter-nextjs is used for Next.js.

❯ ./packages/@apphosting/discover/dist/bin/discover.js starters/nextjs/basic/
{
"discovered": [
{
"framework": "nextjs",
"version": "14.1.4",
"packageManager": "npm",
"platform": "nodejs"
},
{
"framework": "react",
"version": "18.2.0",
"packageManager": "npm",
"platform": "nodejs",
"bundledWith": [
"nextjs"
]
}
]
}

Listed in https://github.com/FirebaseExtended/firebase-framework-tools/blob/main/packages/%40apphosting/discover/src/index.ts

Based on these results, it matches @apphosting/* in the npm registry and is built with a dedicated module

The overall build flow is:
1. `@apphosting/discover` detects the framework based on the presence of dependencies and configuration files.
a. For new creations, `@apposting/create` is used.
2. There is a `@apphosting/create` and `@apphosting/build` for each framework.
a. For Next.js, `@apphosting/adapter-nextjs` is used.
3. `@apphosting/build` analyzes the `.next` directory to generate a `.apphosting/bundle.yaml`.

Management of Build Results

The build process for Next.js generates a .apphosting/bundle.yaml, based on which a container is created, and then configured as an image on Cloud Run via Registry.


headers: []
redirects: []
rewrites: []
runCommand: node .apphosting/server.js
neededDirs:
- .apphosting
staticAssets:
- .apphosting/public

Once deployed, it becomes accessible at the *.hosted.app domain.

Integration with Google Cloud

As an example, copy the starters/nextjs/basic/ from the following repository to your new GitHub repository and deploy it.

https://github.com/FirebaseExtended/firebase-framework-tools/tree/main/starters/nextjs/basic

Google Cloud manages the source code using Cloud Storage, and after building with Cloud Build, the image is pushed to Container Registry. This image is then configured on Cloud Run.


❯ npm init @apphosting
❯ firebase apphosting:backends:create

i === Import a GitHub repository
✔ Connected with GitHub successfully

When you use the command firebase apphosting:backends:create, GitHub authentication is required, and you can set up the connected repository, allowing you to deploy directly.

You can check which resources are being used at https://console.cloud.google.com/apis/dashboard.

Upon observation, the following were being accessed:

Firebase App Hosting API
Developer Connect API
Compute Engine API
Cloud Logging API
Cloud Run Admin API
Secret Manager API
Cloud Pub/Sub API
Artifact Registry API
Identity and Access Management (IAM) API
Cloud Build API
Cloud DNS API

After deloyed, You can verify ISR behavior with /isr.

When updates are made at intervals of 10 seconds, you can see that the content is refreshed in the next response, demonstrating the behavior of ISR (Incremental Static Regeneration).

The response header is here:

< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
< content-type: text/html; charset=utf-8
< date: Wed, 15 May 2024 12:36:23 GMT
< etag: "133xe8xanos9vl"
< server: envoy
< vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Url, Accept-Encoding
< x-nextjs-cache: HIT
< x-powered-by: Next.js
< content-length: 12801
< via: 1.1 google
< cache-control: public,max-age=60,s-maxage=3600,stale-while-revalidate
< cdn-cache-status: miss

Since I have the server that deployed Next.js by Cloud Functions, it be compared.

< HTTP/2 200 
< cache-control: max-age=3600
< content-type: text/html; charset=utf-8
< etag: "4c77324b273ebe1c2d68279d9fcbea803d8bf98cb61b9e567efb33fc9b56421d"
< last-modified: Tue, 06 Sep 2022 13:00:34 GMT
< strict-transport-security: max-age=31556926; includeSubDomains; preload
< accept-ranges: bytes
< date: Wed, 15 May 2024 12:35:51 GMT
< x-served-by: cache-nrt-rjtf7700027-NRT
< x-cache: MISS
< x-cache-hits: 0
< x-timer: S1715776551.099519,VS0,VE117
< vary: x-fh-requested-host, accept-encoding
< alt-svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
< content-length: 8266

Conclusion

Conclusion

The deployment of Next.js on Firebase App Hosting has evolved into a more flexible container-based deployment, transitioning from Cloud Functions to Cloud Run. As everything is hosted on Google Cloud, developers can gain insights into the underlying processes.

--

--