【実録】Nuxt.jsの既存プロジェクトを一足早くNuxt v2へとアップグレードする方法

昨年からどんどん勢いが伸び、今年注目のフロントエンドフレームワークである Nuxt ですが、 Nuxt v2 の発表から一ヶ月以上たち、そろそろ待てなくなってきているかたも多いのではないでしょうか？

この記事では、そんな Nuxt v2 を、先行リリースとして公開されている nuxt-edge を利用する形で、現在実際に Nuxt 1.x が動作している、私の個人開発サービスである[「請求書クラウド SeQueue」](https://sequeue.jp)のアップデートした流れをご紹介いたします。

Nuxt v2 の大きな変更である webpack 4 へのアップグレードは、開発効率の向上に大きく貢献することから、少しでもはやく Nuxt v2 を利用したい！というかたも多いでしょう。

そんなかたのお役に立てることができれば幸いです。

ちゃっちゃと結論だけみたい人は一番下の「まとめ」まで飛んでください。

## プロジェクトの状況

今回アップグレードした SeQueue の状況は以下です。

- nuxt 1.0.0
- @nuxtjs/axios 4.5.0
- @nuxtjs/toast 3.0.1

長らくアップデート作業を怠っていたため、相当古い状況になっていますね。どうせなのでこの際全て最新にしてしまおうかと思います。

@nuxtjs/toast は、実は dependencies に nuxt が含まれていないので、今回は本体及び axios-module のアップグレードとなりそうです。

https://github.com/nuxt-community/modules/blob/master/packages/toast/package.json

## axios-module の追従状況について

nuxt 本体を更新したとしても、 axios-module が "nuxt" パッケージを参照している場合は、依存関係で問題が生じてしまいうまく動かなそうです。
ですので、まずは axios-module の依存関係を見ていきます。

https://github.com/nuxt-community/axios-module/blob/master/package.json

レポジトリを見る限り

```json:package.json
{
  ...
  "dependencies": {
    "@nuxtjs/proxy": "^1.2.4",
    "axios": "^0.18.0",
    "axios-retry": "^3.0.2",
    "consola": "^1.1.4"
  },
  "devDependencies": {
    "codecov": "latest",
    "eslint": "^4.17.0",
    "eslint-config-standard": "11.0.0",
    "eslint-plugin-import": "^2.10.0",
    "eslint-plugin-jest": "^21.15.0",
    "eslint-plugin-node": "6.0.1",
    "eslint-plugin-promise": "^3.7.0",
    "eslint-plugin-standard": "latest",
    "eslint-plugin-vue": "^4.4.0",
    "jest": "^22.4.3",
    "jsdom": "^11.6.2",
    "nuxt-edge": "^2.0.0-25375479.ba18127",
    "standard-version": "latest"
  }
  ...
}
```

という依存状況なので、もう完全に nuxt-edge を使うかたちで問題ないようです。

Nuxt 公式のブログ記事では、 nuxt を nuxt-edge のエイリアスとして貼る方法が紹介されていましたが、今はもう不要ということがわかりますね。

https://medium.com/nuxt/nuxt-2-is-coming-oh-yeah-212c1a9e1a67

## パッケージの削除と更新

特に問題なく更新できることがわかったので更新作業をしてみます。
まずは完全に別パッケージとなるため、 nuxt周りのパッケージを削除してしまいます。

```bash
[potato4d@snowcat sequeue-web (master)] $ yarn remove nuxt @nuxtjs/axios
yarn remove v1.6.0
[1/3] 🗑  Removing module nuxt...
[2/3] 🗑  Removing module @nuxtjs/axios...
[3/3] 📃  Regenerating lockfile and installing missing dependencies...
success Uninstalled packages.
✨  Done in 11.43s.
```

こんな感じで削除されていたら成功です。

次は nuxt を nuxt-edge にして導入してみます。

```bash
[potato4d@snowcat sequeue-web (master)]$ yarn add nuxt-edge @nuxtjs/axios
yarn add v1.6.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 527 new dependencies.
```

こちらも特に問題なく実行でき、 package.json をのぞくと、おおよそ以下のようになっていることでしょう。

```json:package.json
{
  ...
  "dependencies": {
    "@nuxtjs/axios": "^5.3.1",
    "@nuxtjs/toast": "^3.0.1",
    "@potato4d/jpy": "^0.0.1",
    "cookie": "^0.3.1",
    "delay": "^2.0.0",
    "js-cookie": "^2.2.0",
    "lodash": "^4.17.4",
    "nuxt-edge": "^2.0.0-25425967.7d92486"
  },
  ...
}
```

## 実行

アップデートが完了したはずなのできちんと動くか動作確認をしてみましょう。
いつも通り `yarn dev` を実行します。

![Screen Shot 2018-05-07 at 20.30.14.png](https://qiita-image-store.s3.amazonaws.com/0/75633/a1909a21-55ab-acb9-e911-049f769b5284.png)

Nuxt v2 からは webpack 4 へのアップグレードにあわせて、グラフィカルなビルドプログレスと並列ビルドがうまい具合に進化したため、非常に高速かつ快適なビルドが可能となっています。

個人的な体感値ですが、 1.5 倍かそれ以上の有意な差があります。

ビルドが完了したら、普段通り localhost:3000 へとアクセスしてください。

![Screen Shot 2018-05-07 at 20.29.25.png](https://qiita-image-store.s3.amazonaws.com/0/75633/f0fe6b72-9b40-b6f1-405c-d74179a45df2.png)

一応レンダリングが動いていることは確認できました。

## 破壊的変更の追従

この後、ざっとみたところ認証周りに動作しない箇所があり、COOKIEの値を引き回すことが不可能になっていました。
原因は isServer / isClient の廃止によるものであることがわかったため、対応します。

### Migrate from isServer to process.server

Nuxt では、昔は isDev / isServer / isClient などがありましたが、今はすべてこれらは環境変数に移行されており、 process.browser などでアクセス可能となっています。 browser は移行していましたが、他がまだであり、 boolean の箇所が undefined となっていたため、追従します。

それぞれを以下のように書き換えることでこの作業は完了です。

- isClient -> process.browser
- isServer -> process.server

今回は isDev は特に対象にないため無視します。
結果としては、以下のような変更となりました。

```diff:auth.js
export default async function(context) {
-  const { app, store, route, redirect, isServer, req } = context
+  const { app, store, route, redirect, req } = context
-  if (isServer) {
+  if (process.server) {
    // 認証の処理
  } else {
    // クライアントでの処理
  }
  // ...
}
```

### Migrate from requestInterceptor to $axios.onRequest

次は　axios-module の 4.x to 5.x への移行です。
今までは以下のように、 nuxt.config.js にガッツリロジックが露出していましたが、これは　5.x からは通用しないので改めます。

```js:nuxt.config.js
{
  // ...
  axios: {
    credentials: false,
    baseURL: process.env.NODE_ENV == 'production' ? 'https://~~~~~~~~~~~~~' : 'http://localhost:8000',
    requestInterceptor: (config, { store }) => {
      if (store.state.token) {
        config.headers.common['Authorization'] = store.state.token
      }
      return config
    }
  },
  // ...
}
```

`plugins/axios.js` を作り、そのままロジックをまるっと移行します。

```js:axios.js
export default function ({ $axios, store }) {
  $axios.onRequest((config) => {
    if (store.state.token) {
      config.headers.common['Authorization'] = store.state.token
    }
    return config
  })
}
```

あとは plugins に追加してやるだけです。

## デプロイとビルド速度の計測

完了したらあとはデプロイします。 特に変更はないので、 `nuxt build` からの `nuxt` で OK ですが、試しにここでビルド速度の向上を体感してみましょう。

あんまりしっかり測るのも大変なので、何度かビルドしてみて大きな差がないことを確認した最終ビルド結果だけを載せています。

### Nuxt v1

```
クライアントビルド：
Version: webpack 3.10.0
Time: 22505ms

サーバーバンドルの作成:
Version: webpack 3.10.0
Time: 4903ms
```

### Nuxt v2

```
クライアントビルド:
Version: webpack 4.7.0
Time: 19148ms
Built at: 2018-05-07 21:08:09

サーバーバンドルの作成:
Version: webpack 4.7.0
Time: 4491ms
Built at: 2018-05-07 21:08:14
```

サーバーバンドルには有意な差はなく、クライアントが少し高速化したというところでしょうか。
development ビルドは目に見えてはやくなりましたが、最終バンドルは結局 Uglify の時間が支配的なので変わらなかったというようにみえます。

## まとめ

これで移行は一通り完了ですので、ざっと手順と現状をまとめておきます。

- nuxt v2 は nuxt-edge のパッケージ名で導入できる
  - nuxt を nuxt-edge のエイリアスにする方法が公式で紹介されているが、今はもうなくても問題ない
- axios-module を利用しており、利用バージョンが 5.3.x でない場合はアップデートの必要がある
  - 現在の最新である 5.3.1 ではデフォルトが nuxt-edge となる
- アプデするとメリットはある
  - とくに development ビルドで有意な高速化が期待できる
- 破壊的変更の追従は一部必要
  - isServer / isClient / isDev などのフラグを使っている場合は process. に置き換える
  - axios-module の intercepter が古い人は新しい方式に切り替える
- 本番ビルドは変更対応の必要なし
  - 本番ビルドのクライアントビルドは小さいながらも有意な高速化が見られる
  - サーバーバンドルの作成は誤差

SeQueue だけでなく、他も少し触ってみましたが、もう十分 nuxt-edge は新規でなく、アプデする形でも Production ready な印象を受けます。
v1 の alpha~rc のときのような抵抗感を持たずに、やる気がある人がいるなら上げてしまっていいのではないでしょうか。

せっかく強力なフレームワークですので、いち早くその進化を体感していくほうが得られるものは大きいでしょう。

## 宣伝

最後にですが、自分も含めたフリーランスや中小企業仲間のために運用しているWebサービス SeQueue。
機能面はシンプルですが、使い勝手については高評価を受けており、当分ベータ期間で無料で使い放題なので是非利用してみてください。

https://sequeue.jp/