Firebaseで業務アプリケーションを構築しよう 2:Firebase Functions&Hostingにデプロイと動作確認
シリーズ
- Firebaseで業務アプリケーションを構築しよう 1:Nuxt.jsのセットアップ - takeda_san’s blog
- Firebaseで業務アプリケーションを構築しよう 2:Firebase Functions&Hostingにデプロイと動作確認 - takeda_san’s blog
- Firebaseで業務アプリケーションを構築しよう 3:一覧画面と編集画面の追加、CloudStoreにデータの保存 - takeda_san’s blog
- Firebaseで業務アプリケーションを構築しよう 4:GitHub Actionsでデプロイフローの構築 - takeda_san’s blog
前回のあらすじ
Nuxt.jsのセットアップをして動作確認をしました。
takeda-san.hatenablog.com
Firebaseへのデプロイと動作確認
今回はNuxt.jsのアプリケーションをFirebase用にデプロイして、同じように動作確認をします。
firebase-toolsのインストール
Firebaseの初期設定をするには、Firebase CLIが必要です。
npm経由でFirebase CLIをインストールします。
お好みですが、今回はグローバルに入れておきます。
npm install -g firebase-tools firebase login
ここの手順そのまんまです。 Firebase CLI リファレンス | Firebase
Firebaseのプロジェクトを作成する
早速、初期設定を…とやりたいところですがその前に、Firebase上のプロジェクトを作成しましょう。
Firebaseのページの左上の プロジェクトを追加
から新規作成ができます。
(良き感じにただ言われるがままに同意する者としてチェックを入れたり、プロジェクト名を決めたりします)
無事プロジェクトが作成出来たらこんな画面が出るはず。
ついでにCloud Firestoreも後で使うので初期化しておきましょう。
Firebaseの初期設定
前回作ったアプリケーション内でFirebaseの初期設定をします。
先ほど作成したFirebase上のプロジェクトと紐づけるイメージです。
cd <プロジェクトのディレクトリ> firebase init
対話形式でプロジェクトの設定を聞かれますが、
? Are you ready to proceed? <- 元気よくY ? Which Firebase CLI features do you want to set up for this folder? <- 今回はFirestore/Functions/Hostingを使います ? Please select an option: <- Use an existing project ? Select a default Firebase project for this directory: <- プロジェクトは先ほど作成したものを指定します
とここまでやると、無事に…エラーが出ます。
locationを設定せよといわれてます。
Error: Cloud resource location is not set for this project but the operation you are attempting to perform in Cloud Firestore requires it. Please see this documentation for more details: https://firebase.google.com/docs/projects/locations
プロジェクトの設定(歯車マーク)から、 Google Cloud Platform(GCP)リソース ロケーション
を設定します。
適当に近場のasia-northeast1にしておきましょう。
気を取り直してもう一度 firebase init
しましょう。
? What file should be used for Firestore Rules? <- デフォルト firestore.rules ? What file should be used for Firestore indexes? <- デフォルト firestore.indexes.json ? What language would you like to use to write Cloud Functions? <- TypeScript ? Do you want to use TSLint to catch probable bugs and enforce style? <- お好みで(今回はNoにしました) ? Do you want to install dependencies with npm now? <- y ? What do you want to use as your public directory? <- デフォルト public(後で設定変えますがとりあえずはこれ) ? Configure as a single-page app (rewrite all urls to /index.html)? <- y(後で設定変えますがとりあえずはこれ)
ここまでで初期設定が完了して、各種Firebase用のファイルが追加されているはず。
rewriteルールの設定とhosting
前回まではローカルでNuxt.jsを動かしてSSRをしていましたが、今回はその部分をFunctions上で行います。
そのため、rewrite ルールの設定とHostingの設定を前回作成したNuxt.jsアプリ用のものに変更します。
こちらの構成図が非常にわかりやすいです。
これを目指します。
Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する - DMM inside
設定はfirebase.jsonにあるので、それを変更します。
{ "firestore": { "rules": "firestore.rules", "indexes": "firestore.indexes.json" }, "hosting": { "site": "<プロジェクトID>", "public": "app/static", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "function": "ssr" } ] }, "functions": { "source": "functions" } }
変更したのは2点。
- "public": "app/static",
静的ファイルの格納ディレクトリ今回はapp/staticに静的ファイルが置いてあるので、デフォルトから変更
https://firebase.google.com/docs/hosting/full-config?hl=ja#public - "destination": "ssr"
アクセスをssrに集めます
ssrのエンドポイントにアクセスするとNuxt.jsの描画処理を実行するFunctionsが実行されます(これから設定します)
https://firebase.google.com/docs/hosting/full-config?hl=ja#rewrites
Functionsの処理を設定
ssrのエンドポイントにアクセスされたときの動作を定義します。
functions/src/index.ts
を編集。
const functions = require('firebase-functions') const { Nuxt } = require('nuxt') const nuxt = new Nuxt({ buildDir: 'ssr', dev: false }) exports.ssr = functions.https.onRequest(nuxt.render)
nuxtのレンダリング結果を返すだけです。
(importで書きたいのだがわからん…)
ビルドとデプロイ設定
ビルドとデプロイ設定
ソースディレクトリのパスの設定
前回忘れていたのですが、jsconfig.jsonとtsconfig.jsonのパス設定を変えましょう。
それぞれディレクトリにappを付与しておきます。
jsconfig.json
{ "compilerOptions": { "baseUrl": ".", "paths": { "~/*": ["./app/*"], "@/*": ["./app/*"], "~~/*": ["./app/*"], "@@/*": ["./app/*"] } }, "exclude": ["node_modules", ".nuxt", "dist"] }
tsconfig.json
"paths": { "~/*": [ "./app/*" ], "@/*": [ "./app/*" ] },
各種パッケージインストール
ビルドに使うパッケージを入れておきましょう。
(WindowsでもLinuxライクなコマンドが使える!素敵!)
npm install -dev rimraf mkdirp cpx
functions配下にNuxt.jsを動作させるのに必要なパッケージを入れておきます。
プロジェクトルートに置いてあるpackage.jsonのdependenciesにあるものが入っていれば大丈夫です。
今までの設定だとこれを入れれば大丈夫なはず。
cd functions npm install nuxt @nuxt/typescript-runtime @nuxtjs/axios @nuxtjs/eslint-config-typescript element-ui
ここまでで、functions配下のdependenciesはこんな感じになってます。
"dependencies": { "@nuxt/typescript-runtime": "^0.2.3", "@nuxtjs/axios": "^5.8.0", "@nuxtjs/eslint-config-typescript": "^0.1.3", "element-ui": "^2.12.0", "firebase-admin": "^8.0.0", "firebase-functions": "^3.1.0", "nuxt": "^2.10.2" },
ビルドコマンドの設定
package.jsonのscriptの部分を書き換えます。
"scripts": { "dev": "nuxt-ts", "build": "nuxt-ts build && npm run build:copy:ssr", "build:copy:ssr": "rimraf functions/ssr && mkdirp functions/ssr && cpx .nuxt/dist/** functions/ssr/dist", "start": "nuxt-ts start", "generate": "nuxt-ts generate", "deploy": "firebase deploy", "serve": "firebase serve", "lint": "eslint --fix --ext .ts,.js,.vue --ignore-path .gitignore .", "test": "jest" },
nuxt-tsでビルドして生成されたファイル群をfunctions/ssr配下にコピーして、firebase deployでデプロイしてます。
動作確認
functionsとnuxtそれぞれをビルド後のデプロイで動作確認してみましょう。
(functions配下も一気にbuildできるようにしたい…)
cd functions npm run build cd .. npm run build npm run deploy
ログでこんなのが出るので、Hosting URLにアクセスします。
+ Deploy complete! Project Console: https://console.firebase.google.com/project/<プロジェクトID>/overview Hosting URL: https://<プロジェクトID>.firebaseapp.com
ローカル実行と同じ画面が表示されたら、無事成功でございます。
今回の変更点はこちら。
firebase設定の追加 · takedasan/yukito@b7306f3 · GitHub
おハマリ申しポイント
構築時にハマったポイントです。
Error: HTTP Error: 400, Project ‘’ is not a Cloud Firestore enabled project.
FirebaseのコンソールでCloud Firestoreを有効化しましょう。
サイドメニューのDatabaseからCloud Firestoreを選択して 有効化
ボタンで解消します。
なんかHosting URLにアクセスしたけど404になる
下記に書いてある通りなんですが、hostingから動的コンテンツを返すときは、今のところFunctionsでus-central1リージョンを使う必要がありそうです。
素直にデフォルトのus-central1にしましょう。
Cloud Functions locations | Firebase
なんかFunctionsが500エラーで落ちてる
Function配下にも、プロジェクトルートに置いてあるpackage.jsonのdependenciesと同等のパッケージのインストールが必要です。
ちょっと手間ですが、同期させておきましょう。
参考にさせていただきました
『公式を見るのが一番早い』あるエライ人は言った。うん、その通りだと思います。
ドキュメントも整備されていて探しやすい。
Cloud Functions を使用した動的コンテンツの配信とマイクロサービスのホスティング | Firebase
最小構成のサンプルと詳細な説明がわかりやすく
なぜFunctions&hostingでnuxt.jsが動くのかを理解するのに非常に役に立ちました。
また、ビルドのスクリプトは目からうろこでございました。
nuxt.js + firebase (cloud functions) で最小構成SSR | 丸ノ内テックブログ
SPAとSSR、静的アプリケーションと動的アプリケーションの違いが参考になりました。
Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する - DMM inside
次回
FireStoreとつなげて読み書きができるようにします。