Nuxt.js(2.14.3)+express4へのバージョンアップでハマったところ

## 背景
[Subroq](https://subroq.com/)というサービスを開発しており、その管理画面開発に、Nuxt.js(2.14.3)とexpress4を利用しています。

最初にNuxt.jsの2.0.0で開発したのですが、そこから2.14.3へのバージョンアップで色々ハマったので、それについて記載いたします。

## ハマったポイント

### yarn upgradeしたら動かなくなった

何も考えず、`yarn upgrade`してみたら、動かなくなりました。
※普通やらない方がいいです。

色々試行錯誤したのですが、結局解決できなかったため、`npx create-nuxt-app console-subroq`で雛形をつく直しました。

`npx create-nuxt-app`は、言語やフレームワークを選択していって、雛形を作ってくれるコマンドなのですが、その選択支の中に、`server side framework`がないことに気づきました。

昔のバージョンには、存在したのですが、なくなっておりどうすればいいのか路頭に迷いました。
代わりに、`Deployment target`という項目が増えてました。

そして、作成された雛形に`server`ディレクトリが存在せず、困りました。

### express-templateの利用

ググったところ、[express-template](https://github.com/nuxt-community/express-template)というものが、あるみたいなので、そのリポジトリを確認してみました。

[template](https://github.com/nuxt-community/express-template/tree/master/template)ディレクトリ内にサンプルがあるので、cloneして起動して、動くことを確認しました。

ただ、Nuxt2.0.0のserver/index.jsとかなり変わっており、困惑しました。

例えば、以下が2.0.0の時のserver/index.jsです。

```
・・・
async function start () {
  // Init Nuxt.js
  const nuxt = new Nuxt(config)

  const { host, port } = nuxt.options.server

  await nuxt.ready()
  // Build only in dev mode
  if (config.dev) {
    const builder = new Builder(nuxt)
    await builder.build()
  }

  app.get('/api/users', users)
  app.get('/api/test', test)
  app.listen(port, host)
}

start()
```

そして、次が、express-templateのindex.jsです。

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

// Import API Routes
app.use(users)
app.use(test)

// Export express app
module.exports = app

// Start standalone server if directly running
if (require.main === module) {
  const port = process.env.PORT || 3001
  app.listen(port, () => {
    console.log(`API server listening on port ${port}`)
  })
}
```

そもそも、Nuxtモジュールをrequireしていないので、後続の処理がかなり変わってます。

バージョン2.13.0で`nuxt.config.js`に`target`という設定が追加されました。
たぶんこの設定を`server`にすることで、このへんの記述をうまくやってくれるため、不要になったのではないかと推測しております。

[configuration-target](https://ja.nuxtjs.org/api/configuration-target)

また、`module.exports = app`が追加されています。

これもハマったポイントなのですが、`module.exports`しないと、`ServerMiddleware should expose a handle`というエラーがでます。

[2.12.0](https://github.com/nuxt/nuxt.js/pull/6881)あたりで追加されたぽいです。

既存のアプリケーションのコードを上記に合わせ書き換えました。

vue部分のソースコードは、waringがでた部分が少しだけありましたが、ほとんどそのまま移行し、問題なく動くようになりました。

### AmazonLinux2上で起動がうまくいかない

AmazonLinux2上で、`yarn dev`で動かしてみたのですが、以下エラーが発生し、うまく動きませんでした。

なぜか、`Address localhost:3000 is already in use.`のwaringが発生します。

起動前に、`lsof -i:3000`で確認しても、何も起動していません。

起動時に3000番port使われているので、別のportを使うメッセージが表示されます。

![スクリーンショット 2020-08-26 21.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685523/c8748923-cea9-9702-9dc0-3a2f416356b1.png)

起動後に、lsofで確認したところ、なぜかプロセスが２つありました。

```
lsof -i:3000

COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    23234 ec2-user   21u  IPv6 201625      0t0  TCP *:hbci (LISTEN)
```

```
lsof -i:36455

COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    23234 ec2-user   22u  IPv4 201629      0t0  TCP localhost:36455 (LISTEN)
```

開発環境のmacでは、発生していなかったため、かなり悩みました。

結果的に、`express-template`と同じようにlisten処理の部分を書き換えました。

```
app.listen(port)
```
↓

```
・・・
if (require.main === module) {
  const port = process.env.PORT || 3001
  app.listen(port, () => {
    console.log(`API server listening on port ${port}`)
  })
}
```

`require.main === module`とはどういう意味か調べてみたところ、
`node index.js`で起動された場合に、`require.main === module`が`true`になるらしいです。

`nuxt`コマンドで起動した場合にどうなるか確認したところ、ここの処理は、`false`で通りませんでした。

ということは、`app.listen`が必要じゃない？ということなんですかね。

Nuxt.jsのソースコードを見てみましたが、確かに`server`を`listen`している記述があるので、内部で`listen`していて、必要ないのかもしれないです。

この認識であっているか怪しいですが。

### productionリリース

`nuxt build`と`nuxt start`を行い、無事動かすことができました。

deamon化には、foreverを使っており、こんな感じでコマンドを設定しています。

```
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "forever start -c 'nuxt start' ./",
    "generate": "nuxt generate"
  },
```

## 最後に

Nuxt.jsは、バージョンアップが頻繁に行われており、設定とか使い方が、今後も変わる可能性があるので、注意してみていこうかなと思いました。

Subroqは、企業のフリーランスエンジニアの採用や活用を支援するサービスを提供しております。また、フリーランスエンジニア向けの記事も書いておりますので、興味ある方は是非、ご一読いただければと思います。

https://subroq.com