Firebase
ssr
nuxt2

nuxt2 + firebaseでサーバサイドレンダリングする

フロントエンド素人ですが、Nuxt2がリリースされたのでfirebaseでSSRしてみました。
基本的にはほぼNuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現するの内容と変わりません…。

今回のサンプルコードはgithub上に公開しています。
https://github.com/polidog/nuxt2-firebase-ssr

まずはnuxtの環境を用意する

$ mkdir ssr-app
$ cd ssr-app
$ npx create-nuxt-app src

途中「Use a custom server framework」と聞かれますが迷わず「none」にしました。

Firebaseの環境を用意する

$ firebase init hosting
$ firebase init functions
$ cd functions
$ npm i -S nuxt express

Cloud Functions実装をする

SSRするためにfunctions/index.jsに実装していきます。

index.js
const functions = require('firebase-functions');
const express = require('express');
const { Nuxt } = require('nuxt');

const app = express();
const nuxt = new Nuxt({
    dev: false,
    buildDir: 'nuxt',
    build: {
        publicPath: '/assets/'
    }
});

function handleRequest(req, res) {
    res.set('Cache-Control', 'public, max-age=600, s-maxage=1200');
    return new Promise((resolve, reject) => {
        nuxt.render(req, res, (promise) => {
            promise.then(resolve).catch(reject);
        });
    });
}

app.use(handleRequest);

const runtimeOpts = {
    timeoutSeconds: 300,
    memory: '1GB'
}
exports.ssrapp = functions.runWith(runtimeOpts).https.onRequest(app);

ビルド設定を変更する

src/nuxt.conf.jsの設定を変更する

nuxt.conf.js
  /*
  ** Build configuration
  */
  buildDir: '../functions/nuxt',
  build: {
    publicPath: '/assets/',
    extractCSS: true,

    /*
    ** You can extend webpack config here
    */
    extend(config, ctx) {

    }
  }

Hostingの設定を変える

firebase.jsonの設定を変更する

firebase.json
{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [{
      "source": "**",
      "function": "ssrapp"
    }]    
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ]
  }
}

ローカルで動くか検証する

$ cd src
$ npm run build
$ cd ../
$ rm -rf public/*
$ cp -R functions/nuxt/dist/ public/assets
$ cp -R src/static/* public
$ firebase serve --only functions,hosting --project your-project-id

nuxtのbuildとかそのへんをnpmのscriptで実行出来るようにする。

package.json
{
  "name": "nuxt2-firebase-ssr",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "rm -rf public/* && cd src && npm run build && cd ../ && cp -R functions/nuxt/dist/ public/assets && cp -R src/static/* public",
    "serve": "npm run build && cd firebase serve --only functions,hosting"
  },
  "author": "polidog"
}

デプロイ時にbuildしてからデプロイするようにする

firebase.jsonのfunctionsでデプロイ前に実行するコマンドを指定できるので、そこでnpm run buildを指定します

firebase.json
{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [{
      "source": "**",
      "function": "ssrapp"
    }]    
  },
  "functions": {
    "predeploy": [
      "npm run build"
    ]
  }
}

デプロイする

$ firebase deploy --proejct your-project-id

最後に

簡単にSSRな環境を作れるfirebaseはすごいなぁーと。
ただし「Sparkプラン」だとSSRできないので、他のプランに変更してください。