Nuxt.js の配信方法について注意点やメリット・デメリットをまとめた

## 目次
 1. はじめに
 2. Nuxt.js について
 3. Nuxt.js を配信する方法
    4. SSR mode で配信する
    5. SPA mode で配信する
    6. 静的サイトとして配信する
 4. まとめ
 5. 参考リンク

## はじめに

こんにちは、UUUM 株式会社でエンジニアをしております新井と申します。
こちらの記事は、[UUUM Advent Calendar](https://qiita.com/advent-calendar/2018/uuum) 10日目の記事になります。

## Nuxt.js　について

Nuxt.js とは、Vue.js を用いた、フロントエンド構築フレームワークです。
SSR(サーバサイドレンダリング) にも対応しており、サーバサイドを含んだフレームワークとして利用することも可能です。

## Nuxt.js の配信方法

Nuxt.js ですが、配信方法として大きく分けて次の3つがあります。
それぞれの注意点やメリット・デメリットについてまとめました。

1. SSR mode で配信する
2. SPA mode で配信する
3. 静的サイトとして配信する

### SSR mode　で配信する

デフォルトの配信方法です。SSRがやりたいからNuxt.jsを選んだようなケースではこちらを選ぶかと思います。

[公式Document](https://ja.nuxtjs.org/guide/commands#%E3%83%97%E3%83%AD%E3%83%80%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4) 

方法は簡単で、特に設定もなく以下のコマンドを走らせると、デフォルトではポート3000番でNuxt.jsが起動します。

```bash
nuxt build
nuxt start
```

 - メリット
    - SSRによるSEO対策
 - デメリット
    - サーバサイド・クライアントサイド両方で実行されるコードなどに気をつける必要がある
    - 気をつけないとパフォーマンスが簡単に低下する

メリットは言わずもがなです。
デメリットについてですが、サーバサイド・クライアントサイド両方で実行されるようなコードがあるので、そういった部分の場合分けを考えるのが少し面倒だったりします。　サーバサイドで実行するコードなのに、window　オブジェクトを使おうとして注意されたり。
また、ライフサイクルをきちんと把握していないと、 **同じAPIに何度もアクセスしてしまったり**　してパフォーマンスの低下を簡単にしてしまう印象です。


### SPA mode　で配信する

結果としては、普通にVue.jsでアプリケーションを作成した場合とほとんと変わりません。
公式からやり方を引用すると、

>nuxt.config.js 内の mode を spa に変更する
>npm run build を実行する
>生成された dist/ フォルダを、surge、GitHub Pages、あるいは nginx のような静的ファイ>ルのホスティングサービスにデプロイする

とあるのですが、**そのままではちゃんと動きませんので注意が必要です。**
nginxで配信する場合と、 AWS の S3 + CloudFrontで配信する場合を例にとって説明します。

#### nginxの場合

/dist 以下を配信すればいいのだから、こういう風にすればいいだろう、と思われるかもしれません。

```nginx
server {
    ~ 省略 ~

    root /app/dist;
    index index.html;

    ~ 省略 ~
}
```
部分的には動くのですが、一部のページで404となることあります。そういった場合、このようにすれば良いです。

```nginx
server {
    ~ 省略 ~

    root /app/dist;
    index index.html;

    location / {
      try_files $uri /index.html;
    }
    ~ 省略 ~
}
```
意味としては、必ず最後に/dist/index.htmlを見に行くということです。
NuxtでbuildしたSPAでは、SPAの中で生成されたルーティングに対してindex.htmlが作成されたりされなかったり、404や500エラーなどもアプリケーション側で処理しますので、必ず最後にrootにあるindex.htmlに対して処理させる必要があります。

 - メリット
    - (ある程度)早い
    - 動的ルーティングが可能 
    - 認証が必要なページ(会員サイトなど)で使用できる
 - デメリット
    - 配信設定に少し癖がある

#### AWS　S3 + CloudFront の場合

cloudfrontは`/`にアクセスがきた時に、s3 bucketで対応する`/index.html`にアクセスさせることはできても、`/users`のようなurlにアクセスした時に、自動的にs3のbucketで対応する`/users/index.html`にアクセスさせるような動作をすることが不可能です。

そのため、 CloudFrontの Errorpageという設定をする必要があります。

こちらの方が詳しく解説してくださっていました
https://christina04.hatenablog.com/entry/2017/05/25/190000

#### 静的サイトとして配信する

静的配信ですが、認証があるページなどでは使用できませんので注意が必要です。常にpublicなページを配信する場合などに使用しましょう。
メディアサイトやブログなどは適しているのではないでしょうか。

また、動的ルーティングができませんので、動的なurlを構成する部分に関しては、 **事前にすべてのhtmlをAPIなどから生成する必要がある** 点は注意が必要かと思います。

典型的な例をあげますと、次のような動的なurlとapiとの対応があったとします。

`/posts/{post_id}` -> APIのリクエスト先としては`/api/posts/{user_id}`に対応

postのidがそのまま記事urlになるようなパターンですね。
こういった場合、静的配信ではどうするかは公式ドキュメントではこう書いてあります
https://ja.nuxtjs.org/api/configuration-generate/#routes

```js
import axios from 'axios'

export default {
  generate: {
    routes: function () {
      return axios.get('https://my-api/users')
      .then((res) => {
        return res.data.map((user) => {
          return {
            route: '/users/' + user.id,
            payload: user
          }
        })
      })
    }
  }
}
```

これの意味するところは、 **/api/users にアクセスしてusersの全データを取得した後、そのすべてのuserに対して、 /api/users/user_id でapiアクセスをした後対応するurlのhtmlを生成するよ** ってことです。

記事数が半端ないメディアサイトとかでは結構注意が必要な部分かなと思います。

また、当たり前ですがブログやメディアサイトで記事などを更新する方法についても考える必要があります。記事を１つ更新するために、**上記のコードを走らせてすべての記事からhtmlを生成するようなことは避けたい**ですよね。 ~~おとなしくSPAでやろっか~~

 - メリット
    - 当たり前だけどめちゃくちゃ早い
 - デメリット
    - 認証が必要なページでは使用不可
    - 動的ルーティングができない
    - 生成時に、動的ルーテイングするようなページではすべてのurlに対してhtmlを生成する必要がある。
    - メディアサイトなどリソースが頻繁に更新される場合も考慮が必要


## まとめ

Nuxt.jsの 配信方々別の注意点や懸念点についてまとめてみました。
意外と、静的配信もそのための実装が面倒なところがあったり、SPA modeでも配信のための設定が少し癖があったりしますね。やはり、 **SSRで配信する場合が一番楽**なのかなと思いました。
しかし方々で言われているように、**フレームワークとしてのNuxt.js** という一面もありますので、上記のような注意点を認識さえしていれば、SPAや静的配信する場合でも積極的にNuxt.jsは使っていけそうです。

#### メリデメまとめ
SSR

 - メリット
    - SSRによるSEO対策
 - デメリット
    - サーバサイド・クライアントサイド両方で実行されるコードなどに気をつける必要がある
    - 気をつけないとパフォーマンスが簡単に低下する

SPA

 - メリット
    - (ある程度)早い
    - 動的ルーティングが可能 
    - 認証が必要なページ(会員サイトなど)で使用できる
 - デメリット
    - 配信設定に少し癖がある

静的配信

 - メリット
    - 当たり前だけどめちゃくちゃ早い
 - デメリット
    - 動的ルーティングができない
    - 生成時に、動的ルーテイングするようなページではすべてのurlに対してhtmlを生成する必要がある。
    - メディアサイトなどリソースが頻繁に更新される場合も考慮が必要