TL;DR
nuxt.jsもFirebaseも分かってない超初心者がnuxt.jsをFirebaseにデプロイを試みた奮闘記。
参考文献からいいとこ取りしただけなので詳しくはページ下にある「参考文献」をご確認ください。
ポイント
- nuxt.jsをFirebaseにデプロイ
- nuxt.jsは動的アプリケーションでデプロイしたい
-
npm run generate
を使いたくない
-
- Firebase functionsはnode.js v8を使用する
今回のオチ
SparkプランだとFirebase functionsが使えない→SSRできない→ここまで頑張ったのに…
(できなかったんですが、方法としてはあってると思うので方法だけ備忘録として記載)
なにか間違ってるかもなのでご指摘いただけると助かります。
前提
環境
OS: macOS Mojave (バージョン10.14)
node: v8.11.1 (firebase functionsのサポートバージョン)
npm: 5.6.0
説明しないこと
- nuxt.jsインストール
- Firebaseの設定は多少省きます
デプロイするWebアプリ
- nuxt.jsで構築
- PWA
- SPAでない
- 動的アプリケーション
方法
nuxt.jsでアプリを作成
とにかく作る
Firebaseでプロジェクトの作成
Firebaseでプロジェクトを作成します。
- Firebase に移動
- 「プロジェクト作成」からプロジェクトを作る
ローカル環境でfirebase-toolsをインストール
デプロイするときに使用する firebase-tools
をインストールします。
$npm install -g firebase-tools
firebaseの設定
firebase-tools
を使って初期設定を行う。
ログイン
$ firebase login
初期設定
$ cd <<プロジェクトフォルダ>>
$ firebase init
今回 hosting
と functions
を使うのでこの2つを選択。
(他にも使うのであればほかも選択して良いと思います。)
Functionsのセットアップ
=== Functions Setup
A functions directory will be created in your project with a Node.js
package pre-configured. Functions can be deployed with firebase deploy.
? What language would you like to use to write Cloud Functions? (Use arrow keys)
❯ JavaScript
TypeScript
→JavaScriptを選択
? Do you want to use ESLint to catch probable bugs and enforce style? (y/N)
→お好みで
Hostingのセットアップ
=== Hosting Setup
Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.
? What do you want to use as your public directory? (public)
→お好みのディレクトリ名で。ここでは一旦 public
を選択。後ほど変更します。
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N)
→作成したnuxt.jsのアプリに合わせて選択。
セットアップ完了
✔ Wrote public/404.html
✔ Wrote public/index.html
i Writing configuration info to firebase.json...
i Writing project information to .firebaserc...
✔ Firebase initialization complete!
→最終的に publicフォルダと frebase.json
と .firebaserc
が作成される。
各種必要なソースを追加
順不同です。以下ソースをいじります。
- functions/index.js
- functions/package.json
- nuxt.config.js
- package.json
- firebase.json
- (念の為確認).firebaserc
functions/index.js
サーバーサイドレンダリングを行うために以下を設定。
const functions = require("firebase-functions")
const { Nuxt } = require("nuxt")
const express = require("express")
const app = express()
const nuxt = new Nuxt({ buildDir: ".nuxt", dev: false })
function handleRequest(req, res) {
res.set("Cache-Control", "public, max-age=300, s-maxage=600")
return new Promise((resolve, reject) => {
nuxt.render(req, res, promise => {
promise.then(resolve).catch(reject)
})
})
}
app.use(handleRequest)
exports.ssr = functions.https.onRequest(app)
【注意点】
-
new Nuxt
のbuildDir
は変更できますが、後ほど説明するpackage.jsonに合わせて変更する必要があります - exports.ssrは使用するので、これも変更しないほうが良いかと思います
functions/package.json
{
"name": "functions",
"engines": {
"node": "8"
},
"dependencies": {
"express": "^4.16.3",
"firebase": "^5.5.7",
"firebase-admin": "^6.0.0",
"firebase-functions": "^2.0.5",
"firebase-tools": "^5.1.1",
"nuxt": "^2.0.0",
},
"private": true
}
ポイント
- enginesは node.jsのv8を選択
- express/firebase/nuxt/firebase-functionsは必要
- firebase-tools/firebase-adminはなくても良いかも
nuxt.config.js
publicPathの設定を変更します。
やってもやらなくてもいいのですが、デフォルトの _nuxt
が微妙だと思ったら変更。
デフォルトのまま行くぜ!って場合は今後 assets
は _nuxt
で読み替えてください。
module.export = {
// ...
build: {
publicPath: '/assets/',
}
}
package.json
package.json
の scripts
にビルドオプションを追加します。
今回は分かりやすいような名前にしますが、オプション名はお好みで。
{
...
"scripts" : {
"build": "nuxt build",
"build:firebase": "npm run clean && npm run build && npm run copy",
"clean": "rm -rf public && rm -rf .nuxt",
"copy": "mkdir -p public && cp -R functions public/server && cp -R static public/client && cp -R .nuxt public/server && cp -R public/server/.nuxt/dist/client public/client/assets",
}
...
{
ポイント
-
build
: デフォルトのまま変更しません -
clean
: 念の為、デプロイ前に前回の情報を削除します -
copy
: server用のフォルダ、client用のフォルダをpublicフォルダ以下に用意します。nuxt.config.jsのbuildDir
やpublicPath
の設定を変えた場合はここ要注意です。
firebase.json
{
"functions": {
"source": "public/server"
},
"hosting": {
"public": "public/client",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [{
"source": "**",
"function": "ssr"
}]
}
}
ポイント
- hosting, functionsはpublic以下に用意したclient/serverを指定する
- hostingに
rewrites
を追加。functionは functions/index.jsでexportしたssr
を指定する
(念の為確認) .firebaserc
.firebaserc
で指定されているプロジェクト名が作成したプロジェクト名を指しているか確認
{
"projects": {
"default": "<<project_name>>"
}
}
デプロイ前の確認
node_modulesのインストール
functions/package.jsonからインストール
$ cd functions
$ npm install
package.jsonからインストール
$ cd ../ (functionsにいれば)
$ npm install
ビルド
先程用意したスクリプトのオプションでビルドします。
$ npm run build:firebase
ローカルでfirebase hosting/functionsを実行する
$ firebase serve
ブラウザで起動を確認
ポート5000でデプロイされるはずなので http://localhost:5000 にアクセスし起動を確認。問題なければ Ctrl + C
で終了
デプロイ
$ firebase deploy
最終的なフォルダ構成
┬ .nuxt
├ assets
├ components
├ functions
│ ├ node_modules
│ ├ index.js
│ └ package.json
├ layouts
├ node_modules
├ pages
├ plugins
├ public
│ ├ client
│ └ server
├ static
├ store
├ .fireabserc
├ firebase.json
├ nuxt.config.js
└ package.json
以上。
余談
Sparkプランで上記を試したところ、Firebase Functionsで下記エラーが発生。
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions
なにか間違えたのだろうか…Sparkプランじゃできないと言う解釈なのですが、なにかご存知だったら教えてください。
参考文献
Nuxt v2とFirebase(CloudFirestore)でPWA対応Webアプリ開発
【v2対応しました】Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する
FirebaseにホストしていたSPA modeのNuxt.jsをSSRで稼働させるためにやったこと
Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する
Nuxt.js Universal App with SSR via Firebase Functions and Firebase Hosting
nuxt.js + firebase (cloud functions) で最小構成SSR