Production ビルドの Nuxt.js でどうしてもソースマップが見たい時の対処法

## About

Nuxt.js アプリケーションで、ステージング環境でしか再現しないバグがあり、調査の必要が出たものの、 Uglify 層まで含めて隠蔽されていてつらいという人のための Tips。というより作業ログ。

Uglify を切ったほうが読みやすい場合もあるが、現実問題として開発環境で Uglify を切るとあまりにもファイルサイズが大きくてつらい。ということもあるのでそういう人にも。

## 再現環境

Nuxt 1.4.0。 create-nuxt-app でも良かったがより最小限で進めたかったので nuxt/starter ベース。

Vue CLI(v2) or Vue CLI(v3) with `@vue/cli-init` 前提で以下の環境と等価。

```
$ vue init nuxt-community/starter-template nuxt-app
```

## 再現レポジトリ

https://github.com/magitek-telescope/nuxt-show-sourcemap-in-production

## ソースマップの表示方法

隠蔽されているだけで中身は普通の webpack であるため、 webpack の `devtool` 設定を追加してやると良い。
https://webpack.js.org/configuration/devtool/#devtool

nuxt.config.js に以下のような設定を記述する。

※: Nuxt 2.x の場合は webpack 4.x になるため、 mode 設定の都合などでこれらの情報は変わる可能性があります。

```js:nuxt.config.js
module.exports = {
  /*
  ** Headers of the page
  */
  head: {
    title: 'nuxt-app',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Nuxt.js project' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },
  /*
  ** Customize the progress bar color
  */
  loading: { color: '#3B8070' },
  /*
  ** Build configuration
  */
  build: {
    /*
    ** Run ESLint on save
    */
    extend (config, { isDev, isClient }) {
      config.devtool = 'eval-source-map'
    }
  }
}
```

`build.extend` で webpack の設定をそのまま書き換えられるので書き換えると良い。

## 動作確認

適当に明らかにバグりそうなコードを混入させてやるのが手っ取り早い。スタックトレースからどこまできちんとソースマップ化や Uglify の解除がされているかも追うことができる。

以下は `yarn build` を実行後に `yarn start` を押した時の図。
`if (process.browser) { window.hoge() }` を実行させてみると、確かにソースマップがでていて対応するファイル名が表示されているのがわかる。

![Screen Shot 2018-07-26 at 3.08.24.png](https://qiita-image-store.s3.amazonaws.com/0/75633/3018c9c1-02ea-50fc-c739-93418e9f2e50.png)

その上で、エラーが発生している index.vue の部分をクリックすると、正しく詳細のソースコードを読むことができることがわかる。

![Screen Shot 2018-07-26 at 3.08.34.png](https://qiita-image-store.s3.amazonaws.com/0/75633/0f5dff7c-23c7-d933-96d0-d4e0c6f7ef64.png)

これでどうしてもステージングで見たいときに対処できる。大抵の場合、現代的なプロジェクトは Git 管理されているはずなので、確認後の Revert も忘れずに。

## Uglify の切り方(一部)

ついでに全てを切ることは十分程度でできるものではなかったので一旦パスしたが、一部は以下のような設定でオフにできることがわかった。

### babel 側の設定削除

`build.extend` に渡ってくる `config.module.rules` にはいっている babel-loader の設定がデフォでは uglify: true なのでこれを切る。

https://github.com/nuxt/nuxt.js/blob/master/lib/builder/builder.js#L198

```js:nuxt.config.js
{
  // ...
  build: {
    extend (config, { isDev, isClient }) {
      console.log(config.externals = [])
      config.module.rules = [...config.module.rules.map((r) => {
        if (r.loader !== 'babel-loader') {
          return r
        }
        r.options.presets[0][1]['targets']['uglify'] = false
        return r
      })]
    }
  }
}
```

### Uglify Plugin 側の設定

`build.uglify` が設定できる。これは client 側の webpack config に載っている。

https://github.com/nuxt/nuxt.js/blob/master/lib/builder/webpack/client.config.js#L184

```js:nuxt.config.js
{
  // ...
  build: {
    uglify: {
      uglifyOptions: {
        compress: false
      },
      cache: './.cache/'
    },
  }
}
```

## まとめ

- nuxt build -> nuxt start でしか再現しないバグが発生した場合は sourcemap を表示させるとよい
- sourcemap の表示には nuxt.config.js の `build.extend` を使う
- 別途 Uglify を無効化したい場合は以下の2つを無効化するとある程度無効化できる
  - babel-loader の config
  - uglify plugin の config