Vue.jsのバージョンアップについてまとめる

# 概要
今更な話題ですが、Vue.jsのバージョンを2系から3系に上げる
内容についてまとめた記事になります。

本業でそんな話が出ていて、Vueの経験がそこまでないためビビっていたり・・・

## バージョンアップ手順
大まかにやり方をまとめると、
1. Vueのバージョンアップ実施：(2.X→3.X)
1. Vue3移行に伴う破壊的変更の対応 (破壊的とか怖すぎ・・)
1. 仕様確認やテスト (ここは環境によるので解説はしないです)

手順1~2について私自身が必要そうに見えたことを
とりあえず記載するような内容です。

# ① Vueのバージョンアップ実施
以前自分で作成した適当なプロジェクトで、実際にVerUpしていきます！

## ツールのアップグレード
### webpack の場合
vue-loader をアップグレードします。
```
$ npm i -D vue-loader@16
```

### vue-cli の場合
vue upgrade で最新の
@vue/cli-service にアップグレードしましょう！
(この辺は公式や他の記事でも同じようなことが書いてあると思います)

https://v3-migration.vuejs.org/ja/migration-build.html

## vueの更新
package.json でvue を 3.Xに更新しましょう。

## 互換性ライブラリのインストール
@vue/compatをインストールし、Vue2とVue3に互換性を持たせることができます。
```
$ npm install vue@next @vue/compat
```

@vue/compatとは、「移行ビルド」とも呼ばれ
 Vue2系の互換の動作を提供するライブラリです。

 互換性があるので、Vue3にアップデートしてもシステムが止まる
 可能性を減らせますが、3系で非推奨になった機能は警告として表示されたりします。

 :::note warn
互換性とは言ってもあくまで一時的な対応にはなるので、
最終的には全てVue3のAPIを使用することを目指しましょう。
:::

下記はVue3.1に更新した時の例です。
```package.json
"dependencies": {
-  "vue": "^2.6.12",
+  "vue": "^3.1.0",
+  "@vue/compat": "^3.1.0"
   ...
},
"devDependencies": {
-  "vue-template-compiler": "^2.6.12"
+  "@vue/compiler-sfc": "^3.1.0"
}
```

:::note info
「vue/compat」のバージョンは、アップグレードするVueの
バージョンと合わせておくといいかも
:::

## ビルド設定の変更
ビルド設定で、vueを@vue/compatにエイリアスし、
Vueのコンパイラオプションでcompatモードを有効にします。

webpack.config.jsを下記のように更新しましょう。

```webpack.config.js
module.exports = {
  resolve: {
    alias: {
      vue: '@vue/compat'
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compilerOptions: {
            compatConfig: {
              MODE: 2
            }
          }
        }
      }
    ]
  }
}
```

vue-cliの場合も貼っておきます。
公式にも同じ記載があります。

```vue.config.js
module.exports = {
  chainWebpack: (config) => {
    config.resolve.alias.set('vue', '@vue/compat')

    config.module
      .rule('vue')
      .use('vue-loader')
      .tap((options) => {
        return {
          ...options,
          compilerOptions: {
            compatConfig: {
              MODE: 2
            }
          }
        }
      })
  }
}
```

# ② Vue3移行に伴う破壊的変更の対応
Vue3に上げることで必要になる修正を順次行っていきましょう。

## eslint修正
eslint-plugin-vueの8.Xをインストールしましょう。

```
$ npm i eslint-plugin-vue@8 -D
```

次に'plugin:vue/vue3-recommended'に設定を置き換えます。

```.eslintrc.js
 extends: [
-  "plugin:vue/essential",
+  "plugin:vue/vue3-recommended",
 ],
```

## インスタンス作成方法の変更
最初に互換性モードを使えるようにしましたが、
それでも動作しなくなる箇所もあります。

その例として、
インスタンス作成の実装方法が大きく変わっていることです。

```
// Vue 2
new Vue({
  render: h => h(App)
}).$mount('#app');

// Vue 3
import { createApp } from 'vue';
createApp(App).mount('#app');
```
アプリの初期化部分で必ず修正がいるかと。。

## ライフサイクルフックの変更
インスタンスと同様、こちらも修正が必須です。

Vue2でbeforeCreate、createdの中で表現していた処理は、
setup内に処理を記載する形に変更されています。

```
// Vue 2
beforeCreate() { ... },
created() { ... }

// Vue 3
import { onBeforeMount, onMounted } from 'vue';
setup() {
  onBeforeMount(() => { ... });
  onMounted(() => { ... });
}
```

こちらの記事により詳しい内容が記載されてました！

https://qiita.com/whopper1962/items/1a99169ba868f94e4c94

## .sync修飾子を削除
有名な話っぽいですが、Vue3では
.sync 修飾子 が消えて v-model に変更されています。

```
<!-- vue2.X -->
<ChildComponent :title.sync="pageTitle" />

<!-- vue3.X -->
<ChildComponent v-model:title="pageTitle" />
```

https://v3-migration.vuejs.org/ja/breaking-changes/v-model.html#%E7%A7%BB%E8%A1%8C%E6%89%8B%E9%A0%86

## .native 修飾子の削除
お次は.native修飾子です。
.syncと同様に、v-model に変更されています。

## vuex/vue-routerのアップグレード
vuex を v4 にアップグレードする必要があります。

```
$ npm i vuex@4
```

またvue-routerを使用している場合には、v4へアップグレードします。

```
$ npm i vue-router@4
```

:::note warn
上記をアップグレードするとコンパイルエラーが発生する
と思うので、慎重に修正していきましょう。
:::


## VueRouter
VueRouterはクラスではなくなったので、
new VueRouter()の代わりにcreateRouterを使用します。

Vue.use(VueRouter)も不要になるので削除しましょう。

### サンプルコード(vue2)
```main.js
import Vue from 'vue'; // 不要になる
import VueRouter from 'vue-router'; // 不要になる
import App from './App.vue';
import routes from './routes';

Vue.use(VueRouter); // 不要になる

 // vue-routerを使う実装に変更される
const router = new VueRouter({
  routes,
});

new Vue({
  render: h => h(App),
  router,
}).$mount('#app');
```
### サンプルコード(vue3)

```main.js
import { createApp } from 'vue';
import App from './App.vue';
import { createRouter, createWebHistory } from 'vue-router';
import routes from './routes';

// vue-routerを使用
const router = createRouter({
  history: createWebHistory(),
  routes,
});

// インスタンス作成の実装も変わってる
const app = createApp(App);
app.use(router);
app.mount('#app');
```

## 個々の警告をつぶしていく
最終的にバージョンアップによる警告は全て修正しましょう。

Vue2 の動作に依存する依存関係が残っている場合、
切り替えができない可能性があります！

# ③仕様確認やテスト
ここでは解説しませんが、
・修正漏れの確認
・仕様が変わっていないか？
・影響範囲の調査
・画面の表示崩れの有無確認
・試験の実施
等が必要になってくるかと思います。

Vueに限らないですが、バージョンアップは慎重に実施していきましょう！

# 最後に
私個人のプロジェクトで必要な修正はこんな感じでした。
実際の現場の場合は修正すべき箇所が多かったり、この記事以外の
修正内容があると思います。

Vueは移行手順が公式に丁寧に書いてあったので、助かった。。
実際に業務で修正する際もなんとかなるといいな。。

## 参考

https://qiita.com/taisei-ide-lyd/items/4bdfdf6cd9345001795b#:~:text=%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9F%E8%B3%87%E6%96%99-,Vue%203%20%E7%A7%BB%E8%A1%8C%E3%82%AC%E3%82%A4%E3%83%89,-%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%99%E3%83%AB

https://v3-migration.vuejs.org/ja/breaking-changes/

https://zenn.dev/azukiazusa/articles/c8d76eb56f5fd8

https://tech-blog.optim.co.jp/entry/2023/10/30/100000

https://qiita.com/whopper1962/items/1a99169ba868f94e4c94