Nuxt で Express を使いときの reload 問題。

## はじめに
こんにちは。今日も[明治大学 advent calendar](https://qiita.com/advent-calendar/2018/meiji_univ)やっていきます。

アドベントカレンダー忘れてて、数週間前に貯めておいた記事でどうにか繋ぐ。

## Reload 問題
nuxtとapi serverを実装して最高のSSR applicationを作りたいぜ！なんて思うでしょ？
でもね、ググって出てくるnuxt & api serverって思ったより微妙なんだ。どれも、開発時の`reload`が気持ちよくない。

nuxt & expressでググって良く出てくるのは以下の2つのパターン。
1. nuxt as an express middleware
2. express as a nuxt middleware

### 1. nuxt as an express middleware
まずはこっち。nuxtが提供しているexpress middlewareを使うバターン。

#### Example
コードはこれ。見ての通り、 Nuxt builder middlewareをexpressで使う。api serverをNodemonとかでwatch&reloadするような開発と非常に相性が悪い。

```js
const express = require('express')
const { Nuxt, Builder } = require("nuxt")
const app = express()

let config = require("./nuxt.config.js")
config.dev = !(process.env.NODE_ENV === "production")
const nuxt = new Nuxt(config)

if (config.dev) {
    const builder = new Builder(nuxt)
    builder.build()
}

const api = require("./api")

app.use("/api", api)
app.use(nuxt.render)
```

#### Pros and Cons
- Pros
  - 実装が楽
- Cons
  - api server開発時にnuxtを最ビルドする必要があり、DX(Developer Experience)が最悪。


### 2. express as a nuxt middleware
次はこっち。Nuxtのmiddlewareとしてexpressを使うパターン。

#### Example

なんと、NuxtがserverMiddlewareなる機能を提供してくれていて、それを使うと本当に簡単にapi serverを実装できる！しかもね、api serverの変更をwatchしてくれて、server processだけをreloadしてくれるスグレモノ。これこそ、何も考えずにssr開発できるのがnuxtの強みなんだよな。

でもね、このexampleの場合、`/api/index.js`の変更しかwatchしてくれないんだ。だから、`./routes/users`を変更してもserverがreloadされない。

**んーーーーーーーーーーーー、、、惜しいっっっ**

```nuxt.config.js
module.exports = {
  // ...
  serverMiddleware: [
    // API middleware
    '~/api/index.js'
  ]
}
```

```/api/index.js
const express = require('express')

// Create express instnace
const app = express()

// Require API routes
const users = require('./routes/users')

// Import API Routes
app.use(users)

// Export the server middleware
module.exports = {
  path: '/api',
  handler: app
}

```

#### Nuxtならできるだろ？設定でなんとかできないのか？
ということで、Nuxtのソースコードを眺めてみる。ここは、serverMiddlewareのwathcerの部分。

一応、`watch` optionでwatchするファイルやディレクトリを指定することができる。が、Clientをwatchするときにも同じoptionを使うので、serverだけwatchしたいなんて要望には沿わない。

結局、**できなかった**。

[nuxt github: builder.js](https://github.com/nuxt/nuxt.js/blob/e6808c57ef4a2026455485e81741194cbbc0d700/packages/builder/src/builder.js#L542-L558)

```js
  watchServer() {
    const nuxtRestartWatch = concat(
      this.options.serverMiddleware // ← ここ
        .filter(isString)
        .map(this.nuxt.resolver.resolveAlias),
      this.options.watch.map(this.nuxt.resolver.resolveAlias), // watch は watchClient() と共有
      path.join(this.options.rootDir, 'nuxt.config.js')
    )

    this.watchers.restart = chokidar
      .watch(nuxtRestartWatch, this.options.watchers.chokidar) 
      .on('change', (_path) => {
        this.watchers.restart.close()
        const { name, ext } = path.parse(_path)
        this.nuxt.callHook('watch:fileChanged', this, `${name}${ext}`)
      })
  }
```

#### Pros and Cons
- Pros
    - 実装がめっちゃ楽
- Cons
    - 一応、api server only reloadはできるけど、entry pointのみのreloadになるので、完璧なDXとは言えない。

## Temporary Solution
とはいえ、わざわざ、nuxt serverとapi serverを分離させてproxyで...なんて面倒なことやりたくない。nuxtがサポートしてくれるまで寝て待てばいいのだろうけど、ずっと寝ちゃいられない。ということで、苦肉の策だけど、即時的というか一時的な解決策としては、これぐらい。

**webpackとかでbuildしたやつをserverMiddlewareに設定する**

あれ、nuxt serverとapi serverを分離させた方が良いんじゃ、、

## おわりに
もしかして良い方法ってあるの？あったら教えてください☺️
自分だったら頑張って、分離させてproxyでほげほげしちゃうかも。面倒だけどね。typescriptも使いたいし。

### 追記
本当は Rust で Parser Combinator 実装！みたいな内容にしたかったんだけど、Ownership と Lifetime に苦しまされていて何も実装できなかった。Rust でコンビネーターはキツくない？？