Firebase App HostingにNext.jsがデプロイされる仕組み
「Firebase CLIのNext.jsデプロイ対応について調べる」ではCloud FunctionsにカスタムビルドしたNext.jsアプリがデプロイされていたが、Cloud Functions (2nd gen)でCloud RunベースになったのでNext.jsのデプロイもApp HostingでCloud Run版になった
基本的なデプロイまでの手順以下のドキュメントにある。本記事ではこれを参考に内部動作を調べる
firebase-tools
firebase-cliの最新版に以下のコマンドが追加されている
❯ 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.
これを直接実行しなくても管理コンソールからGUIでデプロイできる(Vercelのように)
コンソールからは1つのbackendしか作成できないが、apphosting:backends:create
を実行すると2つ目のbackendが作成できる
firebase-framework-tools
現Cloud Functions版でアプリケーションを微調整する組込みライブラリのfirebase-framework-toolsはApp HostingではCloud Build内部処理に使われるようになっている。このためアプリケーションレベルでの変換はしていないはず
この中の@apphosting系のパッケージがビルドの処理を実装している
Cloud Buildで接続されたGitHubリポジトリからソースコードを取得してフレームワークを自動で検知してCloud Runにデプロイする
例: フレームワーク検知部分を単体で実行する
❯ ./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"
]
}
]
}
この結果を元にnpmレジストリの@apphosting/ - npm searchにマッチされ、専用モジュールでビルドされる
Next.jsの場合の全体のビルドフローは
- @apphosting/discoverがdependenciesや設定ファイルの有無を元にframework検知する
a. 新規作成する時は@apphosting/create - frameworkごとに@apphosting/create、@apphosting/buildがある
a. Next.jsは@apphosting/adapter-nextjs - @apphosting/buildが.next/ディレクトリを解析して.apphosting/bundle.yamlを生成
bundle.yaml
はこういうもの
headers: []
redirects: []
rewrites: []
runCommand: node .apphosting/server.js
neededDirs:
- .apphosting
staticAssets:
- .apphosting/public
.apphosting/
に出力されたファイルをコンテナにして→Registry→Clood Runのimageにセットする
Google Cloud側の動作
以下のリポジトリのstarters/nextjs/basic/
を自分の新規GitHubリポジトリにコピーしてデプロイする
❯ npm init @apphosting
❯ firebase apphosting:backends:create
i === Import a GitHub repository
✔ Connected with GitHub successfully
firebase apphosting:backends:create
するとGitHub認証が要求され接続するリポジトリを設定、そのままデプロイまでできる
どのリソースが使われているかは https://console.cloud.google.com/apis/dashboard から確認できる
観察していたところ以下が叩かれていた
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
Cloud StorageにソースコードがチェックアウトされCloud Buildでビルドしたのちに、Container RegistryにイメージがpushされそれがCloud Runのイメージに設定される
デプロイが完了すると*.hosted.app
というホストにアクセスできる
/isr
でISRの動作を検証できる。
10秒感覚を空けて更新すると、その次のレスポンスでは内容が更新されているのでISRの挙動になっているのが分かる
このサーバーのレスポンスヘッダ
< 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
旧Cloud FunctionsにNext.jsをデプロイしたサーバーがあったので比較
< 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
Cloud Run内のリソース設定を変更する時はapphosting.yamlを用意するとCloud Buildで適用してくれる
カスタムドメインはApp Hosting→Backend→Settingsから設計できる。Google Cloud側には設定がない。
Discussion