【Vue2系・Vue3系】Vue2系からVue3系へアップデートしてみた（環境構築編）

## はじめに
初投稿です。
「Vue2系と3系は違う！」と聞くことは多いけれど「具体的にどのように違うんだろう・・・？」と疑問に思うことが多くありました。
そこで直近、Vue2系学習用に作成したアプリケーションを、Vue3系にリライトしたため、その時の操作を備忘録として残します。

## 環境
| 項目 | Vue2 | Vue3 |
|:-:|:-:|:-:|
|Vueのバージョン|2.6.14|3.5.13|
|その他ライブラリ| vue-roter<br>vue-axios<br>vuex|vue-roter<br>vue-axios<br>vuex |

今回はOptions API→Composition APIへの書き換えは行っていません。

## 1.初期設定
Vue2系とVue3系では初期設定の部分からかなり違います。

### main.js

【2系】
VueのオブジェクトをimportしてAppを立ち上げる

```javascript:main.js/vue2
import Vue from 'vue'
import App from './App.vue'

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

【3系】
Vue3系ではcreateAppで生成したインスタンスを立ち上げる

```javascript:main.js/vue3
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App);
app.mount('#app')

```

# 2.ライブラリの使用

全体的にオブジェクトを生成し、useメソッドで注入する方法から、メソッドをimportしてインスタンスを生成する形に変わっています。

### ①vue-router(router.js)
ページのルーティングに使用しました。

【2系】
(1)Vueオブジェクトを生成し、useメソッドでVuerRouterインスタンスを入れ込むことでライブラリを使用
(2)アクセスモードがhashモード・historyモードがあるが、何も指定しなければhashモードになる
　（参考：https://qiita.com/kozzzz/items/af9ad63fa70d4724cc2a）

```javascript:router.js/vue2
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    // ページ情報を指定
    path: '/login',
    name: 'Login',
    component: Login,
    meta: {isPublic: true}
  },
]

const router = new VueRouter({
  routes,
  base: process.env.BASE_URL,
})

// 公開設定やログイン状態によって遷移ページを変更
router.beforeEach((to, from, next) => {
    if (to.matched.some(record => (record.meta.isPublic || Store.getters.isAuthenticated))) {
        next()
    } else {
        next({path: '/login'})
    }
})

export default router
```

【3系】
(1)createRouterでインスタンスを生成し、作成したインスタンスをexportすることでライブラリを使用
(2)アクセス方法に応じたimportが必要
　（hashモード→createWebHashHistory・hisotryモード→createWebHistory）
 
`````` diff_javascript:router.js/vue3
+ import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: Login,
    meta: {isPublic: true}
  },
  // （中略）
]

+ const router = createRouter({
  routes,
  base: process.env.BASE_URL,
+ history: createWebHashHistory()
})

// 公開設定やログイン状態によって遷移ページを変更
router.beforeEach((to, from, next) => {
    if (to.matched.some(record => (record.meta.isPublic || Store.getters.isAuthenticated))) {
        next()
    } else {
        next({path: '/login'})
    }
})

export default router
``````

### ②vue-store(store.js)
ログイン情報の保存に使用

【2系】
(1)Vueオブジェクトを生成し、作成したVuexインスタンスをuseすることでライブラリを使用
(2)生成したVuexインスタンスの中でStoreを定義

（参考：https://qiita.com/kouki-iwahara/items/1a75daaa93657b0b56d7）

```javascript:store.js/vue2
import Vue from "vue";
import Vuex from "vuex";
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex);

const getAuthState = () => ({
  loginId: null
});

export default new Vuex.Store({
    // 保持する情報を明記
    state: getAuthState(),
    
    // stateの状態の変化によって値を再計算
    getters: {
      isAuthenticated: state => {
        return state.loginId != null;
      },
    },
    mutations: {
      // stateの値を更新するためのメソッドを定義
      updateId(state, loginId) {
        state.loginId = loginId;
      },
    },
    // セッション情報の保存としてcreatePersistedStateを使用
    plugins: [createPersistedState(
    {
      key: 'myApp',
      paths: [
        'loginId'
      ],
      storage: window.sessionStorage,
    }
  )]
});
```

【3系】
(1)vuex内のcreateStoreをimportし、生成したものをexportする

```diff_javascript:store.js/vue3
+ import { createStore } from 'vuex'
import createPersistedState from 'vuex-persistedstate'

const getAuthState = () => ({
  loginId: null
});

+ const store = createStore({
    // 保持する情報を明記
    state: getAuthState(),
    
    // stateの状態の変化によって値を再計算
    getters: {
      isAuthenticated: state => {
        return state.loginId != null;
      },
    },
    mutations: {
      // stateの値を更新するためのメソッドを定義
      updateId(state, loginId) {
        state.loginId = loginId;
      },
    },
    // セッション情報の保存としてcreatePersistedStateを使用
    plugins: [createPersistedState(
    {
      key: 'myApp',
      paths: [
        'loginId'
      ],
      storage: window.sessionStorage,
    }
  )]
});

export default store
```

### ③axios
フロント→バックエンドへのHTTP通信用に使用

【2系】
(1)生成したVueオブジェクトに対して全てのVueファイルでaxiosを使えるように設定

```javascript:main.js/vue2
import axios from 'axios'

// baseURLを設定
axios.defaults.baseURL = 'http://localhost:8080/api';
// cookieを付与
axios.defaults.withCredentials = true;
// 全てのVueファイルでaxiosを使えるように設定
Vue.prototype.$axios = axios;
```

【3系】
(1)createAppで生成したappインスタンスに対して全てのVueファイルでaxiosを使えるように設定

```diff_javascript:main.js/vue3
import axios from 'axios'

// baseURLを設定
axios.defaults.baseURL = 'http://localhost:8080/api';
// cookieを付与
axios.defaults.withCredentials = true;
// 全てのVueファイルでaxiosを使えるように設定
+ app.config.globalProperties.$axios = axios;
```

### ⑤main.jsに適用
【2系】
(1)Vueインスタンスに対し、ライブラリを注入

```diff_javascript:main.js/vue2
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
import router from './router'
import store from './store'

axios.defaults.baseURL = 'http://localhost:8080/api';
axios.defaults.withCredentials = true;
Vue.prototype.$axios = axios;

new Vue({
 router,
 store,
 axios,
 render: h => h(App),
}).$mount('#app')
```

【3系】
(1)1つ1つappインスタンスに対しuseでライブラリを注入

```diff_javascript:main.js/vue3
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import router from './router'
import store from './store'

// axiosの設定
const app = createApp(App);
axios.defaults.baseURL = 'http://localhost:8080/api';
axios.defaults.withCredentials = true;
app.config.globalProperties.$axios = axios;

app.use(router)
app.use(store)
app.use(axios)
app.use(vuetify)
app.mount('#app')
```

## さいごに
今後もVue2系から3系へアップデートした際に、苦労したことなどをまとめていきます。