物置小屋

メモ置き場

Nuxt.jsをSSRモードでFirebaseにデプロイする

はじめに

n番煎じだって感じだけど、メモ書き程度に置いておきます。

使うもの

Nuxt.js

ja.nuxtjs.org

Firebase

firebase.google.com

今回使うのは以下のもの

  • Firebase Hosting
  • Cloud Functions for Firebase
    • Node.jsを動かせるFaaS

やり方

やるだけ

Nuxtプロジェクトを作る

create-nuxt-appを使います。

github.com

$ npx create-nuxt-app ssr-test-app

create-nuxt-app v2.15.0
✨  Generating Nuxt.js project in ssr-test-app
? Project name ssr-test-app
? Project description My fantabulous Nuxt.js project
? Author name mnao305
? Choose programming language JavaScript
? Choose the package manager Npm
? Choose UI framework None
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules Progressive Web App (PWA) Support
? Choose linting tools ESLint
? Choose test framework None
? Choose rendering mode Universal (SSR)
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)

色々と質問されるけどお好みで。
今回は面倒なのでTSは無しで、UI, Serverフレームワークも入れてません。

プロジェクト作成が終わったら一度ローカルで動かしてみる。

Nuxtプロジェクトの一部修正

分かりやすくするためにクライアント向けのディレクトリをまとめます。

nuxt.config.jsに以下を追加。

srcDir: 'client/',

プロジェクトルートにclientというディレクトリを作り、今Nuxtプロジェクト上に存在する全てのディレクトリを移動する。

client
├── assets
├── components
├── layouts
├── middleware
├── pages
├── plugins
├── static
└── store

Firebaseプロジェクトを作る

やるだけ

Nuxtプロジェクト上でFirebaseのセットアップ

いつも通りCLIでセットアップ

$ firebase init

? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. 
 ◯ Database: Deploy Firebase Realtime Database Rules
 ◯ Firestore: Deploy rules and create indexes for Firestore
 ◉ Functions: Configure and deploy Cloud Functions
❯◉ Hosting: Configure and deploy Firebase Hosting sites
 ◯ Storage: Deploy Cloud Storage security rules
 ◯ Emulators: Set up local emulators for Firebase features


? Please select an option: (Use arrow keys)
❯ Use an existing project 
  Create a new project 
  Add Firebase to an existing Google Cloud Platform project 
  Don't set up a default project 

? Select a default Firebase project for this directory:↑で作ったプロジェクト

? What language would you like to use to write Cloud Functions? JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? No
? Do you want to install dependencies with npm now? Yes

? What do you want to use as your public directory? public
? Configure as a single-page app (rewrite all urls to /index.html)? No

後で変えられるし適当に。

Cloud Functions側のコード諸々を書く

node10を使うようにする

以下のように修正

"engines": {
-  "node": "8"
+  "node": "10"
},

Cloud Functionsでnode10を使う場合、Blaze(従量課金)プランにしないといけないので注意。
node8も今後サポート終わるので、Functions使うならプラン上げるの必須になるぽい。

クライアント側の依存パッケージをFunctions側にも入れる

プロジェクトルートのpackage.jsonにあるdependencies内ののパッケージをfunctions側のpackage.jsonに移植します。コピペでOK。
コピペしたらnpm iでインストールしておく。

新しくパッケージを入れたら同じようにコピペしておく。

index.jsの修正

functions/index.jsを編集します。

const functions = require('firebase-functions')
const { Nuxt } = require('nuxt')

const nuxt = new Nuxt({
  buildDir: '.nuxt',
  dev: false
})

exports.ssr = functions.https.onRequest(async (req, res) => {
  await nuxt.ready()
  return nuxt.render(req, res)
})

ちなみにfunctions.region('asia-northeast1').https.onRequest(...みたいな感じに指定すれば東京リージョンが使用できるが、このような動的コンテンツを配信するためにはus-central1リージョンじゃないとダメらしい。(一敗)

公式にも書いてある。

重要: HTTP 関数を使用して Firebase Hosting で動的コンテンツを提供するには、us-central1 を使用する必要があります。

そう考えると読み込み速度的な意味だと微妙な気がする。教えて偉い人。

デブロイ用ビルドコマンド設定

npm scriptとして下記を追加。

"build:firebase": "npm run clean && npm run build && npm run copy",
"clean": "rm -rf public && rm -rf .nuxt",
"copy": "mkdir public && cp -R functions public/server && cp -R client/static public/client && cp -R .nuxt public/server && cp -R public/server/.nuxt/dist/client public/client/assets

Firebase設定ファイルの修正

firebase.jsonを以下のように修正。

{
  "functions": {
    "source": "public/server"
  },
  "hosting": {
    "public": "public/client",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [{
      "source": "**",
      "function": "ssr"
    }]
  }
}

やってる事としてはこんな感じ

ビルド&デプロイ

$ npm run build:firebase
$ firebase deploy

以上。

最終形態のリポジトリ github.com