Next.jsをFirebase Hostingにデプロイする
概要
Next.jsを雰囲気で書いてみたのでデプロイしてみたい
公式を見るとVercelにあげるのがレコメンされてますが
会社ではGCPよく使うので、Firebase Hostingにあげたい!と思いやってみたメモ
参考にしたサイト
公式のExampleによるとSSR(getServerSideProps)させるためか
Firebase HostingへのリクエストをCloud Function For Firebase に流して
Node.jsに実行させてるみたい...
とりあえず素直に公式に従ってやってみる
手順
ディレクトリ構成
こんな感じのディレクトリ構成
Next.jsの公式とかみて適当なpages用意してやってください
※今回と直接関係ないディレクトリもあります🙇♂️
.
├── LICENSE
├── README.md
├── components
├── docker
│ └── nextjs
│ └── Dockerfile
├── docker-compose.yml
├── firebase.json
├── firebaseFunctions.js
├── hooks
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── pages
├── public
├── styles
└── tsconfig.json
docker-composeでとりあえずローカル環境準備
version: '3.8'
services:
nextjs:
build: ./docker/nextjs
container_name: nextjs
volumes:
- ./:/usr/src/app
command: "npm run dev"
ports:
- "3000:3000"
FROM node:15.4.0-alpine3.10
WORKDIR /usr/src/app
上記ファイル準備してビルド&起動
docker-compose up -d --build
Cloud Functionsで実行するファイル用意
Firebase HostingへのリクエストがこっちにきてNext.jsを捌いてくれる
distDirで.next指定してるので、next build
で出力された.next
ディレクトリを指定
const { https } = require("firebase-functions");
const { default: next } = require("next");
const isDev = process.env.NODE_ENV !== "production";
const nextjsServer = next({
dev: isDev,
conf: {
distDir: ".next",
},
});
const nextjsHandle = nextjsServer.getRequestHandler();
exports.nextjsFunc = https.onRequest((req, res) => {
return nextjsServer.prepare().then(() => nextjsHandle(req, res));
});
package準備
こんな感じで準備してnpm install
すれば依存入ってきます
(ポイントとしては★でコメントした部分
{
"name": "ucwork-frontend",
"version": "0.1.0",
"private": true,
"main": "firebaseFunctions.js", // ★1 Cloud Function For Firebaseにデプロイするjsファイル
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"deploy": "firebase deploy --only functions,hosting", // ★2 こいつでFirebaseのHostingとFunctionsにデプロイ
"logs": "firebase functions:log", // ★3 なんかエラーあった時これで詳細見れるので便利
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"dependencies": {
"@material-ui/core": "^4.11.1",
"@material-ui/icons": "^4.9.1",
"firebase-admin": "^9.4.2", // ★4 この辺はmustで必要
"firebase-functions": "^3.13.0", // ★4
"i18next": "^19.8.4",
"next": "10.0.3",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-i18next": "^11.8.3",
"recharts": "^1.8.5"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@storybook/addon-actions": "^6.1.10",
"@storybook/addon-essentials": "^6.1.10",
"@storybook/addon-links": "^6.1.10",
"@storybook/react": "^6.1.10",
"@types/node": "^14.14.10",
"@types/react": "^17.0.0",
"babel-loader": "^8.2.2",
"firebase-tools": "^9.0.1",
"prettier": "^2.2.1",
"typescript": "^4.1.2"
}
}
firebase関連の設定
Firebase Functionsへのデプロイ前に
npm run build
でnext build
実行してる感じ
{
"hosting": {
"public": "public",
"rewrites": [
{
"source": "**/**",
"function": "nextjsFunc"
}
]
},
"functions": {
"source": ".",
"predeploy": [
"npm --prefix \"$PROJECT_DIR\" install",
"npm --prefix \"$PROJECT_DIR\" run build"
],
"runtime": "nodejs12"
}
}
デプロイ
あとはnpm run deploy
実行すると、こんな感じでdeploy成功する
npx firebase login --no-localhost
でログインが必要かも
/usr/src/app # npm run deploy
> ucwork-frontend@0.1.0 deploy
> firebase deploy --only functions,hosting
=== Deploying to ...
...
✔ functions[nextjsFunc(us-central1)]: Successful update operation.
i hosting[xxx]: finalizing version...
✔ hosting[xxx]: version finalized
i hosting[xxx]: releasing new version...
✔ hosting[xxx]: release complete
✔ Deploy complete!
気になったポイント
コールドスタート重い
初回アクセス(しばらくアクセスしてない)時はCloud Functionsの起動に時間かかるのでかなり重め
リージョン変えると動かない
Cloud Functionsデプロイリージョンをasia-northeast1(東京)
に変えたらブラウザでうまく表示されなくなった
Cloud Functionsのoriginはus-central1である必要があるみたい
まとめ
初回(結構時間経った時)アクセスするとかなり重いので
中途半端にSSRせずに、SWRでAPI連携することで、Firebase Hostingだけで動かないのかしら...🤔
ということでもう一声Next.jsで遊んでみることにする
Discussion
Next.js on Firebase以前試したことがあるのですが、パフォーマンス的にSSRが厳しいのですよね。
リージョンを変えると動かない件、ドキュメントにしれっと書かれていますね…。
SSRをしなくても良いのであればNext.jsのStatic HTML Exportで生成された静的ファイルをそのままFirebase Hostingにあげて、動的なデータはクライアントでのマウント後にSWRなどで取得するのが良いのかも?🤔
コメントありがとうございます!
近い方がいいでしょ。と思い無邪気にリージョン変えてみましたがちゃんとドキュメントに書いてあったんですね😫
とりあえず公式のexampleを見つけたんでやってみたんですが
かなり重かったのでコメントいただいたとおり
next export
してFIrebase HostingにデプロイAPIはSWRで呼び出す作戦をまさにローカルで試みてました🧔
実験したらまた自分の勉強メモようにまとめようと思います🙇♂️