SSRで作ったnuxt projectをFirebase hostingにデプロイする方法

# SSRで作ったnuxt projectをFirebase hostingにデプロイする方法
と言う記事です。
主に自分の備忘録として書きます。

## SSRって何よ？
詳しくは下記から。
[SPA、SSR、プリレンダリングの違いをまとめてみた](https://qiita.com/amakawa_/items/e7d0720e1ab8632769bf)

SPAは
- jsonやxml形式のデータをレスポンスする
- ブラウザ側でデータを描画

SSRは
- htmlをレスポンス
- ブラウザ側でhtmlを描画

と言ったところでしょうか。

## firebase hostingって何よ？
firebase公式
[Firebase Hosting を使ってみる](https://firebase.google.com/docs/hosting/quickstart?hl=ja)

- 静的アセットをhostingできるサービス

## 実際に使ってみる
### nuxt project作成

```
$ yarn create nuxt-app <project-name>
```

### firebase login
```
$ firebase login
```

### firebase init
```
$ firebase init
```

いろいろ聞かれる。
hostingを選択。

## SSRでdeploy

### /firebase.jsonを編集する

```/firebase.json
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "functions": { //追記
    "functions": {
      "source": "functions"
    }
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [ //追記
      {
        "source": "**",
        "function": "ssr"
      }
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}
```
後ほどのfirebase serve, firebase deploy のコマンドは、この設定ファイルを読み込んで実行されます。

>functionsは、Firebase Functionsで動作するSSRの実行関数(js)部分の場所を指定しています。

つまり、functions/index.jsが実行されます。

>hostingは、Firebase Hostingで静的配信するhtmlがある場所を指定しています。

つまりpublicディレクトリのことを指しています。

>rewritesは、静的ルートへのアクセスをSSRのルートへ飛ばします。sourceでどのページを飛ばすか、functionでどの関数に飛ばすかを指定しています。ここでは、"**"(全て)を"ssr"(あとで定義する関数)へ飛ばすことにしています。

つまり、全てのページをssrを使って処理すると言うことです。

### /functions/package.jsonを編集する
```/functions/package.json
{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "serve": "firebase emulators:start --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
+    "node": "10"
  },
  "main": "index.js",
  "dependencies": {
    "@nuxtjs/axios": "^5.12.2",
    "@nuxtjs/vuetify": "^1.11.2",
    "firebase-admin": "^8.10.0",
    "firebase-functions": "^3.6.1",
+    "nuxt": "^2.14.7"
  },
  "devDependencies": {
    "firebase-functions-test": "^0.2.0"
  },
  "private": true
}

```

>
- firebase Functionsで実行するnodeのバージョンを指定します。ここでは、 v10を指定します。ちなみに、Firebaseの制約で8か10しか指定できません(2019.11.25現在)
- また、firebase Functionsで実行する際に必要なNuxtをdependenciesに追加。
- 追加したあとで、npm install でnuxtをインストール。
- 外部パッケージを使用する際はさらに追記してnpm install

### /functions/index.jsを編集or作成する

>このファイルが/firebase.jsonのfunctionsで実行されるjsファイルです。
firebase.jsonのrewritesで指定した"ssr"はここに作成するexports.ssrです。

```/functions/index.js
// firebase Functions読み込み
const functions = require('firebase-functions')
// nuxt読み込み
const { Nuxt } = require('nuxt')
// nuxtインスタンス作成
const nuxt = new Nuxt({
  buildDir: 'ssr',
  dev: false,
})

exports.ssr = functions.https.onRequest(async (req, res) => {
  await nuxt.ready()
  return nuxt.render(req, res)
})
```
buildDir で指定する 'ssr' は、**/functions/ssr**ですが、この次でこの場所に必要なファイルをコピーする設定をします。

### /package.jsonを編集する

```/package.json
"scripts": {
    "dev": "nuxt",
    "build": "nuxt build && npm run build:copy:ssr", // 追記
    "build:copy:ssr": "rimraf functions/ssr && mkdirp functions/ssr && cp -R .nuxt/dist functions/ssr/dist", //追記
    "start": "nuxt start",
    "generate": "nuxt generate"
  },
```

読んでコードの如くです。
npm run buildを叩くと、buildされてbuild:copy:ssr scriptが走ります。
その中ではfinctions/ssrを一度削除し作成し直します。
その後.nuxt/distをコピーしfunctions/ssr/distにペーストします。

### ローカル環境でプレビュー&デプロイ

```
$ firebase serve
```
実行するとhttp://localhost:5000
が立ち上がります。

その後

```
$ firebase deploy
```
を行って終わりです。

なお、sparkプランだとfunctionsは使えないみたいです。
しのごの言わずにBlazeプランにしてgoogle様を拝めましょう。

この記事は
[Nuxt.jsで作ったSSRなwebサービスをfirebaseにデプロイする](https://agelog.hateblo.jp/entry/2019/11/25/001401)
を参考に作成しました。
非常にわかりやすかったです。