Azure WebAppsにNuxt.js+Expressの環境をデプロイするために頑張ったメモ

# 前置き
先日 @n0bisuke さんが Qiita に書いた記事「[Azure Web AppsにNuxt.js+Expressの環境をDockerでデプロイしたときのメモ](https://qiita.com/n0bisuke/items/412f2fcc673513866e44)」に、
> けっこうハマって@horihiroさんに色々質問して助けてもらいました。

と書いていただきましたが、実際は一緒にハマってた上、中が Windows の方の Web Apps と勘違いして、見当違いな調査をしてたりしました。
\# n0bisuke さんが動かしたかったのは、Web Apps for Containers （前述の記事）、または [App Service on Linux](https://dotstud.io/blog/azure-webapps-nuxt-express/) でした。

ただ、見当違いながら、Windows の方の Web Apps (以下、Web Apps)の方も調べた結果、いろいろ分かったのでメモとして残しておきます。

# なぜ Web Apps で nuxt-community/express-template が動かないのか

いくつか理由があって、大まかにはこんな感じです。

1. Web Apps の中の node.js は、名前付きパイプで listen してる。
2. node.js から 自分自身に接続する時、"localhost" を使って接続できない。

## Web Apps の中の node.js は、名前付きパイプで listen してる。
一つ目。
node.js の net.Server では、[UnixSocket と 名前付きパイプで listen をサポート](https://nodejs.org/api/net.html#net_identifying_paths_for_ipc_connections)しています。
Web Apps では、node.js を動かす際にこの機能を使用しています。

これは、Web Apps 上で動かしている node.js のサーバーアプリ内で、

```js
console.log(process.env.PORT);
```
などとやると、"\\\\.\pipe\foobar..." と出力されるので、すぐわかります。

node.js に限った話ではないですが、Web Apps では、クライアントからのリクエストを IIS で受信します。
それから各種ランタイムへリクエストが渡されるようなのですが、node.js の場合は、IIS から [iisnode](https://github.com/Azure/iisnode) というモジュールを使用して node.js へリクエストが渡されます。

この時、iisnode と node.js の間は TCP/IP ではなく、名前付きパイプで通信します。

一方で、[nuxt-community/express-template](https://github.com/nuxt-community/express-template) の package.json では、nuxt.js のバージョンに "latest" が指定されており、2018/09/10 時点では v1.4.2 がインストールされます。
しかしながら、nuxt.js での Unix Socket および、名前付きパイプのサポートは、現在 dev ブランチである v2 系列からのようです。

  [feat(core, cli): builtin support of https and unix sockets](https://github.com/nuxt/nuxt.js/pull/3831)

なので、名前付きパイプをサポートしていない nuxt.js v1.4.2 を使っている限り、現在の nuxt-community/express-template の Web Apps 上での動作は難しいと思います。

じゃあ nuxt.js を v2 にしたら問題ないのか、と検証にしようとしましたが、うまくビルドすらできずに挫折しました。

## node.js から 自分自身に接続する時、"localhost" を使って接続できない。
二つ目。
nuxt.js で SSR する時は、内部的な Web API 実行 (HTTP GET /api/users など ) を、"localhost" に向けてリクエストでおこなっているようです。
一方で、Web Apps では localhost への接続が、なぜかできません。
よって、SSR 時の API 実行が失敗します。

クライアントから Web API の実行はできる（GET /api/users は成功する）が、SSR したページが開かない（GET / は失敗する）時は、これを疑った方がいいです。

上記の通り、node.js は名前付きパイプで listen しているので、直接アクセスしたい場合は、SSR 時にも名前付きパイプに対してリクエスト実行すると "localhost" へのアクセスと同様の結果が得られ~~ると思います(が、未検証です)~~ました。

他の SSR エンジンも、内部的な API 実行を "localhost" 経由で行っている場合は失敗すると思うんですが、React とかもそうなんですかね？

# じゃあどうしたら動くのか
nuxt.js と nuxt-community/express-template を独自に書き換える必要があります。

名前付きパイプでの listen ができるように、nuxt.js を Fork し、1.x 系でも[名前付きパイプでも listen できるよう少し書き換えた](https://github.com/horihiro/nuxt.js/commit/161c1066be670e7226ed98fc6400c99c0364d047)のがこちら。

**horihiro/nuxt.js**
https://github.com/horihiro/nuxt.js

一方、nuxt-community/express-template で作ったテンプレートをベースに、SSR 時の API 実行を "localhost" ではなく ~~Web Apps の FQDN~~[名前付きパイプでアクセスする修正](https://github.com/horihiro/nuxt-express-azure-webapps/commit/715fabbd12f9c654292c0f611d134b4115558247)、および、[nuxt.js 自体を上記の名前付きパイプ対応版に差し替えた](https://github.com/horihiro/nuxt-express-azure-webapps/blob/master/package.json#L23)のがこちら。

**horihiro/nuxt-express-azure-webapps**
https://github.com/horihiro/nuxt-express-azure-webapps

horihiro/nuxt-express-azure-webapps を Fork して、![Deploy to Azure](https://azuredeploy.net/deploybutton.png) ボタンをクリック、で Azure へデプロイできるようにしたつもりです。
お試しあれ。

# 注意事項

上のリポジトリについて聞きたいこと、「動かねーじゃねーか」みたいな苦情があれば、Azure サポートではなく、この記事にコメントや、リポジトリに issue を挙げてください。
よろしくお願いいたします。

# 以下、関連ついーと

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/nuxtjs?src=hash&amp;ref_src=twsrc%5Etfw">#nuxtjs</a> の <a href="https://twitter.com/hashtag/UnixSocket?src=hash&amp;ref_src=twsrc%5Etfw">#UnixSocket</a> , <br> <a href="https://twitter.com/hashtag/NamedPipe?src=hash&amp;ref_src=twsrc%5Etfw">#NamedPipe</a> 対応は、2.x (dev branch) の最新コミット。1.x は Azure WebApps (Win) じゃ動かなそう。<a href="https://t.co/nOKsYognDL">https://t.co/nOKsYognDL</a></p>&mdash; ほりひろ😎 (@hori__hiro) <a href="https://twitter.com/hori__hiro/status/1038410945205133313?ref_src=twsrc%5Etfw">2018年9月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">うぬぅ、使い方でどうにかならんか頑張ったけど、やっぱり <a href="https://twitter.com/hashtag/nuxt?src=hash&amp;ref_src=twsrc%5Etfw">#nuxt</a> 自体に手を入れないと無理か。。。</p>&mdash; ほりひろ😎 (@hori__hiro) <a href="https://twitter.com/hori__hiro/status/1038572410037915648?ref_src=twsrc%5Etfw">2018年9月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet" data-conversation="none" data-cards="hidden" data-lang="ja"><p lang="ja" dir="ltr">できたー。<a href="https://twitter.com/hashtag/Azure?src=hash&amp;ref_src=twsrc%5Etfw">#Azure</a> <a href="https://twitter.com/hashtag/WebApps?src=hash&amp;ref_src=twsrc%5Etfw">#WebApps</a> 専用の <a href="https://twitter.com/hashtag/nuxtjs?src=hash&amp;ref_src=twsrc%5Etfw">#nuxtjs</a> &amp; <a href="https://twitter.com/hashtag/express?src=hash&amp;ref_src=twsrc%5Etfw">#express</a> のテンプレート。公式テンプレートを Fork して、少し修正してる。ついでにデプロイ ボタンも付けた。<a href="https://t.co/xnXkEsoEbc">https://t.co/xnXkEsoEbc</a></p>&mdash; ほりひろ😎 (@hori__hiro) <a href="https://twitter.com/hori__hiro/status/1038751609310785538?ref_src=twsrc%5Etfw">2018年9月9日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">あと <a href="https://twitter.com/hashtag/nuxtjs?src=hash&amp;ref_src=twsrc%5Etfw">#nuxtjs</a> 自体にも手を入れないといけなかったので、1.x 系を Fork した。<a href="https://t.co/3Rq32ZDpEX">https://t.co/3Rq32ZDpEX</a></p>&mdash; ほりひろ😎 (@hori__hiro) <a href="https://twitter.com/hori__hiro/status/1038751956280307713?ref_src=twsrc%5Etfw">2018年9月9日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>