はじめに
私は、最近まで営業職としてハウスメーカーで働いていましたが、今年の3月から全く畑違いの世界でエンジニアとして新しいキャリアをスタートさせました。
そんなエンジニア歴1年に満たない私が、2023年12月31日にVue2の公式サポートが終了するとのことで、Vue2の社内ツールをVue3に移行しました。その際の実際の手順を残したいと思います。
基本方針
ハードだと聞いていたので、以下の方針で進めました。
- Vue及びそれに関するライブラリの対応のみ行う
- コードはなるべく変更しない方向で対応する
移行手順
ライブラリの事前調査
Vue3に対応していないライブラリが既にあることがわかっていたので、他のライブラリについても事前に調査し以下の3つに分けました。
1.Vue3に対応済みである
2.Vue3に対応していないが代替えライブラリがある
3.Vue3に対応しておらず代替えライブラリがない
少し手間でしたが、事前に調査していたおかげでエラー箇所の把握に役立だったので、しておいてよかったです。
移行作業
基本的に公式のマイグレーションガイドに沿って実施しました。
1. 最新の @vue/cli-service
にアップグレード(vue-cliを使用している場合):
vue upgrade
2. packege.json
の修正:
移行ビルドをインストールして、vueも3.x系の同じバージョンにします。
yarn add @vue/compat
3. vue.config
の修正:
Vue2 のコードを Vue3 と互換性を持たせるために以下のように設定します。
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
}
}
}
})
}
}
4. コンパイルエラーの解消:
地道に1つずつ解消していきます。私はここで1700くらいの数のコンパイルエラーが出て少し焦りました。一部ですが出てたエラーと解決した方法です⇩⇩
エラー①
[vue/compiler-sfc] This experimental syntax requires enabling one of the following parser plugin(s): "jsx", "flow", "typescript".
原因はこんな感じで書いてるからでした。
<script>
export default {
data() {
return {
options: {
headings: {
sortHandle: (
<span class="wrapper">
<span class="handleIcon" />
</span>
),
name: 'グループ(タブ)',
members_count: '人数',
created_date: '追加日',
members: '',
delete: ''
},
}
}
},
}
</script>
どうやら<script>
タグ内のjsxをparserできないらしい。。
Vue3では、<script>
タグにlang="jsx"属性を追加することで簡単にJSXを組み込むことができるみたいでしたので、<script lang="jsx">
としました。
エラー②
Module not found: Error: Can't resolve '/static/ic_sort_asc.svg' in '~/path'
vue2ではpublic配下の画像は/public
も省いて普通に画像パスを入力すれば表示されていたのですが、 なぜかpath解決できなくなってました。。なので
url('/static/ic_sort_asc.svg')
と書いてたところを
url('public/static/ic_next_chunk_disabled.svg')
に書き換えてコンパイルエラーはなくなりました。
5. main.ts
の修正:
Vueグローバルインスタンスが廃止になったので、main.ts
を以下のように修正します。
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
const app = createApp(App)
app.use(router)
app.use(store)
app.mount("#app")
6. vue-router
vuex
のアップグレード:
vue-router, vuexをそれぞれ4.x系にアップデートし、修正します。
7. Vue3へのアップデートに伴う破壊的変更を修正:
warningが出ていたりするので、エラーも見ながら修正していきます。以下対応した破壊的変更です。
- v-deepセレクタ
//変更前
::v-deep {
.hoge {
color: #fff;
}
}
//変更後
:deep(.hoge) {
color: #fff;
}
- v-model
//変更前
<AppInput :value="pageTitle" @input="pageTitle = $event" />
//変更後 valueをmodelValueに、@input を@update:modelValueに変更します
<AppInput
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
- filterの削除 etc...
8. ライブラリのアップデートや置き換え:
私的にここが一番の山場でした。Vue3に対応していてもかなりの変更があったり、代替えライブラリを使えるか試したり、、、。ダッシュボード系の社内ツールなのでライブラリに頼っているところも多少あり、なかなか苦戦しました。
ライブラリの対応中、よくこんなエラーが出ていました⇩
Uncaught TypeError: Cannot read property '_c' of undefined
vue3と互換性がないエラーみたいなのですが、この記事を参考にライブラリをvue3対応のバージョンにアップデートするとエラーは消えました!
今回の移行作業で以下のライブラリをバージョンアップしたり、置き換えたりしました。
ライブラリ名 | ver | 代替えライブラリ | 備考 |
---|---|---|---|
vue-select | 4.0.0-beta.6 | ||
vue-chartjs | 5.2.0 | ||
vee-validate | 4.12.1 | v3とv4は別物。v2→v4はかなり重かったです。 | |
vue-tables-2 | x | v-tables-3 | 当初vue-tables-3に置き換え、使えるかと思いきやvue3には対応しておらず使えませんでした。 |
vue-toasted | x | vue-toastification | |
vue2-timepicker | x | vue3-timepicker | vue2-timepickerのvue3対応ver |
vuejs-datepicker | x | @vuepic/vue-datepicker | 代替えライブラリはドキュメントがあり、導入記事も豊富でした。 |
まとめ
- 移行作業は計画的に行うべし。
- ライブラリのバージョンやメンテナンスされてるかは常に気にした方がいい。
- 推奨されているviteの導入やVuexをPiniaにするなども随時やっていきたい。
vue2のサポートが終了することはかなり前からわかっていました。もう少し早めに取り組んでもよかったなと感じつつ、Vue3に移行した記事も多くあり助けられた面もありました。
また、移行作業中ビルドにけっこう時間がかかるなという気づきがあったので、落ち着いたらviteの導入もチャレンジしたいと思います。