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

フロントエンド素人ですが、Nuxt2がリリースされたのでfirebaseでSSRしてみました。
基本的にはほぼ[Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する]([Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する - DMM inside](https://inside.dmm.com/entry/2018/04/10/nuxt-firebase))の内容と変わりません…。

今回のサンプルコードは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できないので、他のプランに変更してください。