Vue.js / Nuxt.jsのアプリをnginxで動かす（サブディレクトリ対応）

先日、[Vue.js / Vue.js + TS / Nuxt.js / Nuxt.js + TSでポケモンのタイプ相性表を実装してみる](https://qiita.com/ktkiyoshi/items/49e8593578e141b475d1)という記事を書きましたが、実装した4つのアプリをサーバで動かすにあたり、少し苦戦したのでまとめておこうと思います。

# 概要
全く同じ挙動を示すアプリを、Vue.jsとNuxt.js、及びそれぞれでTypeScriptを使った計4パターンの構成で実装してみる、というものでした。

- vue-cli-app
- vue-cli-ts-app
- nuxt-app
- nuxt-ts-app

というアプリ名だったわけですが、これらを同時に同じサーバ上で動かしたい！

## 何が難しいか

ローカルで、`npm run serve`または`npm run dev`すると、デフォルトでは`localhost:3000`などで起動します。

しかし、同時に同じサーバ上で、となると、同じポートを使うわけにはいかず、かつドキュメントルートをどこにするか、また、Webサーバ側の設定は？プロキシは？といった問題も出てきます。

## 目指すURL（結論）

- https://kt-kiyoshi.com/vue-cli-app
- https://kt-kiyoshi.com/vue-cli-ts-app
- https://kt-kiyoshi.com/nuxt-app
- https://kt-kiyoshi.com/nuxt-ts-app

前回は、題材をポケモンのタイプ相性表として、`/type`というパスになるようにしたので、上記のURLの後ろに`/type`を付けるとアクセスできます。（ページ内にリンクも一応張ってあります）

# vue-cli / vue-cli + TypeScript

今回は、JavaScriptなのかTypeScriptなのかは関係ないのでまとめて書いていきます。

## publicPathの設定

それぞれのアプリに応じた公開パスを設定に追記します。アプリ側の設定変更はこれだけです。

```javascript:vue.config.js
// vue-cli-app
module.exports = {
    publicPath: '/vue-cli-app'
}

// vue-cli-ts-app
module.exports = {
    publicPath: '/vue-cli-ts-app'
}
```

## ビルド & 起動

ローカルは`npm run serve`でしたが、サーバ上（本番環境とする）で動かす際は、ビルドを行います。なお、今回のアプリは`/usr/local/app/`配下に置くものとします。

```
$ cd /usr/local/app/vue-cli-app
($ cd /usr/local/app/vue-cli-ts-app)
$ npm install
$ npm run build

> vue-cli-app@0.1.0 build /usr/local/app/vue-cli-app
> vue-cli-service build

⠼  Building for production...
 DONE  Compiled successfully in 4556ms                                                            21:38:01

  File                                 Size               Gzipped
  dist/js/chunk-vendors.159a8d6a.js    133.84 KiB         46.27 KiB
  dist/js/app.140e3f96.js              7.33 KiB           2.70 KiB
  dist/js/about.9b96da1f.js            0.44 KiB           0.31 KiB
  dist/css/app.b49d9da6.css            1.09 KiB           0.52 KiB

  Images and other types of assets omitted.

 DONE  Build complete. The dist directory is ready to be deployed.
 INFO  Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
```

これでビルドは完了しました。特に起動コマンドなどはありません。

## ドキュメントルートからの参照

distディレクトリに対するシンボリックリンクを作ることにしました。（rootになっているのは気にしないでください）

```
$ cd /var/www/html
$ ln -s /usr/local/app/vue-cli-app/dist vue-cli-app
($ ln -s /usr/local/app/vue-cli-ts-app/dist vue-cli-ts-app)

$ ls -l vue-cli-*
lrwxrwxrwx 1 root root 31 10月  6 23:12 vue-cli-app -> /usr/local/app/vue-cli-app/dist
lrwxrwxrwx 1 root root 34 10月  7 20:57 vue-cli-ts-app -> /usr/local/app/vue-cli-ts-app/dist
```
## proxyの設定（nginx）

```nginx:/etc/nginx/conf.d/default.conf
# vue-cli-app
location /vue-cli-app {
    alias /var/www/html/vue-cli-app;
    try_files $uri $uri/ /vue-cli-app/index.html;
}

# vue-cli-ts-app
location /vue-cli-ts-app {
    alias /var/www/html/vue-cli-ts-app;
    try_files $uri $uri/ /vue-cli-ts-app/index.html;
}
```
`Vue.js`のほうは以上です。

# Nuxt.js / Nuxt.js TypeScript

こちらも言語問わず、なので、`Nuxt.js`の動かし方、として書いていきます。

## routerの設定

`vue.js`の時は`publicPath`でしたが、今回は`router`の`base`を設定します。やや縦長なので`nuxt-ts-app`のほうは読み替えてください。

```javascript:nuxt.config.js
export default {
  mode: 'universal',
  router: {
    base: '/nuxt-app/'
  },
  /*
  ** Headers of the page
  */
  head: {
    base: {
      href: 'router.base'
    },
// 略
```
この方法は一応、[公式ガイド](https://ja.nuxtjs.org/api/configuration-router/)にも書いてあるのですが、いまいち以下の記述はよくわかりませんでした。。（とりあえず`head`に入れておきます）

> `base` がセットされているときは Nuxt.js はドキュメントのヘッダーに `<base href="{{ router.base }}"/>` を追加します。

参考）[Nuxt.jsでサブディレクトリにデプロイするときの対応](https://designsupply-web.com/knowledgeside/5383/)

## proxyの設定（nginx）

`vue.js`のそれとは異なり、こちらは`proxy_pass`を使います。ここで注目すべきは、片方のポート番号を`3001`としていることです。

```nginx:/etc/nginx/conf.d/default.conf
# nuxt-app
location /nuxt-app/ {
    proxy_pass http://127.0.0.1:3000/nuxt-app/;
    proxy_redirect http:// https://;
}

# nuxt-ts-app
location /nuxt-ts-app/ {
    proxy_pass http://127.0.0.1:3001/nuxt-ts-app/;
    proxy_redirect http:// https://;
}
```
参考）[Nginxのlocationとproxy_passの末尾スラッシュによる挙動の違いを理解する](https://kuroeveryday.blogspot.com/2019/03/effect-of-trailing-slash-on-nginx-reverse-proxy.html)
## ポート番号の設定

`nuxt.config.js`で起動時のポート番号を設定できます。

```javascript:nuxt.config.js
// nuxt-ts-app
server: {
  port: 3001
},
```

## ビルド
ここまできたらいよいよビルドします。

```
$ npm install
$ npm run build
```

## 起動

今回は`npm run start`ではなく、`pm2`で起動することにします。

### PM2のインストール

公式サイトは[こちら](http://pm2.keymetrics.io/)。

```
$ npm install -g pm2
```

### 起動
アプリのルートディレクトリ直下で行います。

```
$ pm2 start npm --name nuxt-app -- start
($ pm2 start npm --name nuxt-ts-app npm -- start)
```
### 確認

```
// ステータス
$ pm2 status
┌─────────────┬────┬─────────┬──────┬───────┬────────┬─────────┬────────┬──────┬───────────┬──────┬──────────┐
│ App name    │ id │ version │ mode │ pid   │ status │ restart │ uptime │ cpu  │ mem       │ user │ watching │
├─────────────┼────┼─────────┼──────┼───────┼────────┼─────────┼────────┼──────┼───────────┼──────┼──────────┤
│ nuxt-app    │ 0  │ N/A     │ fork │ 9104  │ online │ 0       │ 2D     │ 0.2% │ 22.5 MB   │ root │ disabled │
│ nuxt-ts-app │ 4  │ N/A     │ fork │ 10967 │ online │ 1       │ 2D     │ 0.2% │ 30.6 MB   │ root │ disabled │
└─────────────┴────┴─────────┴──────┴───────┴────────┴─────────┴────────┴──────┴───────────┴──────┴──────────┘

// ログ
$ pm2 log
/root/.pm2/logs/nuxt-app-out.log last 15 lines:
0|nuxt-app |
0|nuxt-app | > nuxt-app@1.0.0 start /usr/local/app/nuxt-app
0|nuxt-app | > nuxt start

// モニター
$ pm2 monit
```
`id`がちょっと飛んでいるのはミスって削除したからです・・・

### 削除
```
// processを全部消す時
$ pm2 kill

// 特定のprocessを消すとき
$ pm2 delete {id}
```

### 停止
```
$ pm2 stop {App name}
```

### 再起動
```
$ pm2 restart {App name}
```

---

`Vue.js`はすぐでしたが、`Nuxt.js`はサブディレクトリ対応に苦戦しました。トップページは出るのに`_nuxt`などのパスがどうしてもサブディレクトリ配下にならなくて・・・。

完全に理解したとは言い難いですが、取り急ぎこれで問題なく動いているのでOKかな、と思います。