複数環境を持つNuxt.jsベースのアプリで、webpack由来の環境変数のトラブルを回避する

ステージング環境・本番環境など、複数の環境向けに環境変数を定義したファイルを用意して、generate/build実行時にスイッチさせてファイルを生成させたいのに

```
✔ Skipping webpack build as no changes detected
```
みたいなメッセージが出て、中途半端な成果物が出力されることがある問題への対応メモです。

（記事内のpackage.jsonは、必要な項目以外は省略しています。）


## せっかちな人向け
```json:package.json
{
  "dependencies": {
    "nuxt": "^2.14.7",
  }
}
```
`v2.14.7`以上のNuxt.jsを利用する。


## 中途半端な成果物が出力される現象
開発環境用の成果物を生成後、ファイルの変更なしに本番環境用の成果物を生成する場合に、冒頭のようなログが出力されました。

いざ中身を確認してもほぼ開発環境の状態で、利用可能な本番向けの成果物が出力されていませんでした。
（Vueのインスタンス生成前には本番環境向けのタイトルが表示され、実際のレンダリングされるページには開発環境向けの内容が表示される。）


## ひとまずの雑な回避方法
(今回はNuxt.js/TypeScriptの環境で確認したもののため、nuxt-tsを利用しています)

ひとまず、nuxt-tsのオプションを確認します。

```zsh
% npx nuxt-ts generate --help
  Usage: nuxt generate <dir> [options]

  Generate a static web application (server-rendered)

  Options:

    --spa, -s          Launch in SPA mode
    --universal, -u    Launch in Universal mode (default)
    --config-file, -c  Path to Nuxt.js config file (default: nuxt.config)
    --modern, -m       Generate app in modern build (modern mode can be only client)
    --target, -t       Build/start app for a different target, e.g. server, serverless and static
    --no-force-exit    Whether Nuxt.js should force exit after the command has finished
    --version, -v      Display the Nuxt version
    --help, -h         Display this message
    --no-processenv    Disable reading from process.env and updating it with dotenv
    --dotenv           Specify path to dotenv file (default: .env). Use false to disable
    --no-lock          Do not set a lock on the project when building
    --no-build         Only generate pages for dynamic routes, used for incremental builds. Generate has to be run once without this option before using it
    --devtools         Enable Vue devtools
    --quiet, -q        Disable output except for errors
    --force-build      Force to build the application with webpack
    --fail-on-error    Exit with non-zero status code if there are errors when generating pages

```

`--force-build`オプションが利用できるみたいなので、package.jsonのscriptsの項目を編集して追加します。
（未確認ですが、出力を見る限りではnuxtコマンドのオプションでも利用できそうです。）

```json:package.json
{
  "scripts": {
    "generate:dev": "cross-env NODE_ENV=\"development\" nuxt-ts generate --force-build",
    "generate:prod": "cross-env NODE_ENV=\"production\" nuxt-ts generate --force-build",
  }
}
```
この対応でひとまずプロジェクト上での問題は解決しました。

## 検証環境で問題が再現されない
この記事を書くために、デモのプロジェクトを作成して再現しようとしましたが、

```
ℹ Doing webpack rebuild because env changed
```
と出力され、ちゃんとビルドが走って成果物もちゃんと出力されるんですよね。

なんでかな？と思ってたんですけど、どうもプロジェクト環境とデモ環境でNuxt.jsのバージョンが異なり、かつデモ環境のバージョンでは環境変数の変化を検知するようになっているようでした。

## v2.14.7から環境変数に変化があった場合に再ビルドが行われる
Nuxt.jsのリリース一覧を覗いて、その理由がわかりました。
https://github.com/nuxt/nuxt.js/releases/tag/v2.14.7
> Rebuild if process.env changes in nuxt.config

v2.14.7の変更で、process.envの変更を検知するよう改善されたようです。
デモ環境でのNuxt.jsのバージョンは2.14.7、プロジェクト環境ではその時2.14.0でした。
そりゃうまいこといくわぁ...

## 最終的な対応
まず、Nuxt.jsのバージョンを2.14.7以上を利用するよう変更します。

```json:package.json
{
  "dependencies": {
    "nuxt": "^2.14.7",
  }
}
```
package.jsonのscriptsの項目は、オプションなしでgenerateを実行するようにします。

```json:package.json
{
  "scripts": {
    "generate:dev": "cross-env NODE_ENV=\"development\" nuxt-ts generate",
    "generate:prod": "cross-env NODE_ENV=\"production\" nuxt-ts generate",
  }
}
```
ファイル変更後、最新のNuxt.jsをインストールして対応は終わりです。

```zsh
% npm i -D
```