Vue3 でプロジェクトを作成する 〜 VueCLI 変更点 確認編 〜

## Prologue

Vue3 のプロジェクトの立ち上げ方と Vue2 -> Vue3 の移行が現状どのようになっているのか確認するために検証を行いました。

Vue3や使用している CLI 等は今後変更があると思いますので、自身で設定する場合には都度公式を確認することをお勧めします。

## 環境

- macOS: v10.15.6
- node.js: v12.18.2
- terminal: iTerm
- エディタ: VS Code
- パッケージマネージャ: `yarn`

## install

vueCLI v4.5.0 で Vue3 のプロジェクトを選択できるようになりました。

参考: 

- https://github.com/vuejs/vue-cli/releases/tag/v4.5.0
- https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md
- https://v3.vuejs.org/guide/

今回 バージョンが `Vue CLI v4.4.6` だったため、 `yarn global add @vue/cli` を実行し、バージョンを上げます。
参考: https://github.com/vuejs/vue-cli/releases

以下のコマンドを実行してバージョンの確認の確認をし、問題なければOKです。

```
vue -V 
@vue/cli 4.5.4
```

### プロジェクトの作成 : Default Vue 3 Preview を選択

`vue create vue3-next` コマンドを実行します。今回プロジェクトは `vue3-next` としています。 

```
Vue CLI v4.5.4
? Please pick a preset: 
  Default ([Vue 2] babel, eslint) 
❯ Default (Vue 3 Preview) ([Vue 3] babel, eslint) 
  Manually select features 
```

デフォルトで Vue3 が選択できるようになっています。感動。

`package.json` を確認します。

``` JS 
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0-0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0-0"
  },
```

`yarn.lock` も確認してみます。

``` JS 
vue@^3.0.0-0:
  version "3.0.0-rc.10"
  resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-rc.10.tgz#31298a757b4fad6ee8973d0fa27c4fde8574bd01"
  integrity sha512-nRsyIQtOWLDMBb5dsPwg/WdIqznCMVWN6O6wJSzhseKC768wHlZKcJ7SPHhWPid9wi3Ykhtl9vtgvxTK/qICkw==
  dependencies:
    "@vue/compiler-dom" "3.0.0-rc.10"
    "@vue/runtime-dom" "3.0.0-rc.10"
    "@vue/shared" "3.0.0-rc.10"
```

`vue3.0.0-rc.10` がインストールされていて、 `yarn serve` を実行し問題なく表示されて入ればOKです。

### プロジェクトの作成 : Manually select features を選択

`manually select` を選択します。

```
Vue CLI v4.5.4
? Please pick a preset: 
  Default ([Vue 2] babel, eslint) 
  Default (Vue 3 Preview) ([Vue 3] babel, eslint) 
❯ Manually select features 
```

次に Vue のバージョンの選択肢が表示されるため、3.x を選択します。

```
? Choose a version of Vue.js that you want to start the project with 
  2.x 
❯ 3.x (Preview) 
```

以下はこれまで通り、自分が使うモジュール等を選択していきます。

```
vue create vue3-next-manually


Vue CLI v4.5.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Rou
ter, Vuex, Linter
? Choose a version of Vue.js that you want to start the project with 3.x (Previe
w)
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfi
lls, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback 
in production) Yes
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated confi
g files
? Save this as a preset for future projects? No
```

`manually select` だと従来通り TS も選択できるため、TS を使用したい方はこちらを選択すると設定周りも楽になります。(`Default (Vue 3 Preview)` だと手動で入れる必要があります。)
 
`package.json` を確認します。

``` JS 
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0-0",
    "vue-class-component": "^8.0.0-0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-0",
    "prettier": "^1.19.1",
    "typescript": "~3.9.3"
  }
```
次に `yarn.lock` も確認してみます。

``` JS 
vue@^3.0.0-0:
  version "3.0.0-rc.10"
  resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-rc.10.tgz#31298a757b4fad6ee8973d0fa27c4fde8574bd01"
  integrity sha512-nRsyIQtOWLDMBb5dsPwg/WdIqznCMVWN6O6wJSzhseKC768wHlZKcJ7SPHhWPid9wi3Ykhtl9vtgvxTK/qICkw==
  dependencies:
    "@vue/compiler-dom" "3.0.0-rc.10"
    "@vue/runtime-dom" "3.0.0-rc.10"
    "@vue/shared" "3.0.0-rc.10"
```

以上、2種類の操作を試しましたが、Vue3 のバージョンに違いがないことを確認しました。こちらも `yarn serve` を実行して画面が表示されればOKです。

### プロジェクトの作成 : Manually select features を選択, class-style component を使わない

ここでは CompositionAPI を使いたい場合、 `class-style component` を選択しないと違いがあるのかを検証しています。

プロジェクトの作成

```
vue create vue3-next-manually-no-class 


Vue CLI v4.5.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Rou
ter, Vuex, Linter
? Choose a version of Vue.js that you want to start the project with 3.x (Previe
w)
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfi
lls, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback 
in production) Yes
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated confi
g files
? Save this as a preset for future projects? No
```

`package.json` を確認します。
 
``` JS 
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0-0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-0",
    "prettier": "^1.19.1",
    "typescript": "~3.9.3"
  }
```

 `yarn.lock` も確認してみます。

``` JS 
vue@^3.0.0-0:
  version "3.0.0-rc.10"
  resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-rc.10.tgz#31298a757b4fad6ee8973d0fa27c4fde8574bd01"
  integrity sha512-nRsyIQtOWLDMBb5dsPwg/WdIqznCMVWN6O6wJSzhseKC768wHlZKcJ7SPHhWPid9wi3Ykhtl9vtgvxTK/qICkw==
  dependencies:
    "@vue/compiler-dom" "3.0.0-rc.10"
    "@vue/runtime-dom" "3.0.0-rc.10"
    "@vue/shared" "3.0.0-rc.10"

// 略

vuex@^4.0.0-0:
  version "4.0.0-beta.4"
  resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.0.0-beta.4.tgz#7b319ead2ef30432b7eaa4e37258ea3c5e44f698"
  integrity sha512-/+4E1dokq5cwbl4mohOqOj8h0vOLOWmLSqlqTf++bfmN9/JKWtwYfsBrzlK0sYrNfuYcpQeX0BVxQHoHXDfYZQ==

// 略

vue-router@^4.0.0-0:
  version "4.0.0-beta.9"
  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.0-beta.9.tgz#8552c38c9b015527e74c9c6cb4c54868219d601e"
  integrity sha512-k8AGMm3LCTqnsEuF37AD4kcZVMwtnFEzdjACgmIII/xbLnTj3+o5XyH/zREBZutgv5q2hzlLltMVglqDQYMd/A==
``` 

` "vue-class-component": "^8.0.0-0"` がないだけとなります。この辺りも従来通りという感じです。

#### CompositionAPI が使えるか確認

Vue2 までは plugin の `CompositionAPI` を import して使う必要がありましたが、Vue3 ではその必要が無くなったということで、実際書いてみます。

`src/components/HelloWorld.vue` を以下のように変更

- before

``` JS
<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: String
  }
});
</script>
```

- after

``` JS
<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: {
      type: String
    }
  },
  setup(props) {
    const message = `${props.msg}. + Vue3`;
    return { message };
  }
});
</script>
```

`before` の時点で `vue` から `defineComponent` が import されているため使えることは当たり前なのですが、念のため `setup` 等も追記してみました。
追加したテキスト等が表示されていればOKです。

---

## 既存のプロジェクトをVue3 に変更

ここからが一番使うのではないでしょうか。
まずはVue2 でプロジェクトを作成します。今回プロジェクト名は `vue3-next-cli-plugin` としました。
TS, Vuex, vue-router も一緒にインストールしていきます。

```
vue create vue3-next-cli-plugin           


Vue CLI v4.5.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Rou
ter, Vuex, Linter
? Choose a version of Vue.js that you want to start the project with 2.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfi
lls, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback 
in production) Yes
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated confi
g files
? Save this as a preset for future projects? No
```

`package.json` の中身を確認します。

``` JS 
"dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^1.19.1",
    "typescript": "~3.9.3",
    "vue-template-compiler": "^2.6.11"
  }

```

`yarn.lock` の中身も確認します。

``` JS 
vue@^2.6.11:
  version "2.6.12"
  resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
  integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==

//

vuex@^3.4.0:
  version "3.5.1"
  resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d"
  integrity sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw==

//

vue-router@^3.2.0:
  version "3.4.3"
  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.3.tgz#fa93768616ee338aa174f160ac965167fa572ffa"
  integrity sha512-BADg1mjGWX18Dpmy6bOGzGNnk7B/ZA0RxuA6qedY/YJwirMfKXIDzcccmHbQI0A6k5PzMdMloc0ElHfyOoX35A==
```


`HelloWorld.vue` は以下の通り。

``` JS
<script lang="ts">
import Vue from "vue";

export default Vue.extend({
  name: "HelloWorld",
  props: {
    msg: String
  }
});
</script>
```

以上は、以下から行う比較のために参考として置いておきます。


### `vue add vue-next` で Vue3 を入れる

参考: https://github.com/vuejs/vue-cli-plugin-vue-next

コマンドを実行します。

```
vue add vue-next

📦  Installing vue-cli-plugin-vue-next...

yarn add v1.22.4
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
success Saved 2 new dependencies.
info Direct dependencies
└─ vue-cli-plugin-vue-next@0.1.3
info All dependencies
├─ vue-cli-plugin-vue-next@0.1.3
└─ vue-loader@16.0.0-beta.5
✨  Done in 4.19s.
✔  Successfully installed plugin: vue-cli-plugin-vue-next


🚀  Invoking generator for vue-cli-plugin-vue-next...
📦  Installing additional dependencies...

yarn install v1.22.4
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 7.65s.
⚓  Running completion hooks...

✔  Successfully invoked generator for plugin: vue-cli-plugin-vue-next
 vue-next  Installed vuex 4.0.
 vue-next  Documentation available at https://github.com/vuejs/vuex/tree/4.0
 vue-next  Installed vue-router 4.0.
 vue-next  Documentation available at https://github.com/vuejs/vue-router-next
```

インストールが完了しました。次に `package.json` の中身を確認してみます。

``` JS 
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0-beta.1",
    "vue-router": "^4.0.0-alpha.6",
    "vuex": "^4.0.0-alpha.1"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-beta.1",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-alpha.0",
    "prettier": "^1.19.1",
    "typescript": "~3.9.3",
    "vue-cli-plugin-vue-next": "~0.1.3"
  }
```

yarn.lock の中身も確認します。

``` JS 
vue@^3.0.0-beta.1:
  version "3.0.0-rc.10"
  resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0-rc.10.tgz#31298a757b4fad6ee8973d0fa27c4fde8574bd01"
  integrity sha512-nRsyIQtOWLDMBb5dsPwg/WdIqznCMVWN6O6wJSzhseKC768wHlZKcJ7SPHhWPid9wi3Ykhtl9vtgvxTK/qICkw==
  dependencies:
    "@vue/compiler-dom" "3.0.0-rc.10"
    "@vue/runtime-dom" "3.0.0-rc.10"
    "@vue/shared" "3.0.0-rc.10"

// 略

vuex@^4.0.0-alpha.1:
  version "4.0.0-beta.4"
  resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.0.0-beta.4.tgz#7b319ead2ef30432b7eaa4e37258ea3c5e44f698"
  integrity sha512-/+4E1dokq5cwbl4mohOqOj8h0vOLOWmLSqlqTf++bfmN9/JKWtwYfsBrzlK0sYrNfuYcpQeX0BVxQHoHXDfYZQ==

// 略

vue-router@^4.0.0-alpha.6:
  version "4.0.0-beta.9"
  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.0-beta.9.tgz#8552c38c9b015527e74c9c6cb4c54868219d601e"
  integrity sha512-k8AGMm3LCTqnsEuF37AD4kcZVMwtnFEzdjACgmIII/xbLnTj3+o5XyH/zREBZutgv5q2hzlLltMVglqDQYMd/A==
```

`package.json` では `vue: ^3.0.0-beta.1` となっていましたが、`yarn.lock` で最新版が落とされていることを確認しました。`vue-router`, `vuex` も同様です。

#### Error の解消

このままで `yarn serve` を実行すると、エラーが出ます。

``` JS 
 ERROR  Failed to compile with 6 errors                                 22:57:58

Module Error (from ./node_modules/vue-loader/lib/index.js):
[vue-loader] vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options.

// 略

Module build failed (from ./node_modules/vue-loader/lib/index.js):
TypeError: Cannot read property 'parseComponent' of undefined
    at parse (/Users/mi**/work/vue3-next-cli-plugin/node_modules/@vue/component-compiler-utils/dist/parse.js:15:23)
    at Object.module.exports (/Users/mi**/work/vue3-next-cli-plugin/node_modules/vue-loader/lib/index.js:67:22)

// 略

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.
ERROR in src/main.ts:6:11
TS2345: Argument of type 'typeof import("/Users/mi**/work/vue3-next-cli-plugin/node_modules/vue/dist/vue")' is not assignable to parameter of type 'Component'.
  Type 'typeof import("/Users/mi**/work/vue3-next-cli-plugin/node_modules/vue/dist/vue")' is not assignable to type 'ComponentOptionsWithObjectProps<any, any, any, any, any, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, Readonly<{ [x: string]: any; }> | Readonly<...>>'.
    Type 'typeof import("/Users/mi**/work/vue3-next-cli-plugin/node_modules/vue/dist/vue")' is not assignable to type 'ComponentOptionsBase<Readonly<{ [x: string]: any; }> | Readonly<{ [x: string]: any; } & { [x: number]: any; }>, any, any, any, any, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string>'.
      Types of property 'watch' are incompatible.
        Type '{ <T extends readonly (object | Ref<unknown> | ComputedRef<unknown> | (() => unknown))[], Immediate extends boolean = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchOptions<...> | undefined): WatchStopHandle; <T, Immediate extends boolean = false>(source: WatchSource...' is not assignable to type 'Record<string, ComponentWatchOptionItem>'.
          Index signature is missing in type '{ <T extends readonly (object | Ref<unknown> | ComputedRef<unknown> | (() => unknown))[], Immediate extends boolean = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchOptions<...> | undefined): WatchStopHandle; <T, Immediate extends boolean = false>(source: WatchSource...'.
    4 | import store from "./store";
    5 | 
  > 6 | createApp(App)
      |           ^^^
    7 |   .use(router)
    8 |   .use(store)
    9 |   .mount("#app");

ERROR in src/router/index.ts:1:10
TS2305: Module '"../../node_modules/vue-router/dist/vue-router"' has no exported member 'RouteConfig'.
  > 1 | import { RouteConfig, createRouter, createWebHistory } from "vue-router";
      |          ^^^^^^^^^^^
    2 | import Home from "../views/Home.vue";
    3 | 
    4 | const routes: Array<RouteConfig> = [

ERROR in src/store/index.ts:3:21
TS2339: Property 'createStore' does not exist on type '{ Store: typeof Store; mapState: Mapper<Computed> & MapperWithNamespace<Computed> & MapperForState & MapperForStateWithNamespace; ... 4 more ...; createLogger: <S>(option?: LoggerOption<...> | undefined) => Plugin<...>; }'.
    1 | import Vuex from "vuex";
    2 | 
  > 3 | export default Vuex.createStore({
      |                     ^^^^^^^^^^^
    4 |   state: {},
    5 |   mutations: {},
    6 |   actions: {},

ERROR in src/views/Home.vue:12:20
TS2339: Property 'extend' does not exist on type 'typeof import("/Users/mi**/work/vue3-next-cli-plugin/node_modules/vue/dist/vue")'.
    10 | import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
    11 | 
  > 12 | export default Vue.extend({
       |                    ^^^^^^
    13 |   name: "Home",
    14 |   components: {
    15 |     HelloWorld
```


一つずつ修正していきます。

#### src/**.vue 内を CompositionAPI に則した形で書く

component 内が `Vue.extend` のままなので、修正します。こちらは問題なく終了。

#### createApp について

こちらは Vue3 での変更点となります。

参考: https://github.com/vuejs/rfcs/blob/49de6decac4dc99840410d082e3bd7c98b580193/active-rfcs/0009-global-api-change.md

変更点: GlobalAPI の再設計によって、`createApp` が作成され、それによりアプリインスタンスのみにスコープされるようになりました。

自動で書き換えられていますが、型に関する変更を手動で行う必要があります。

`shims-vue.d.ts` の変更
参考: https://github.com/vuejs/vue-next-webpack-preview/issues/5

調べると以下の方がより型に沿っているそうなのですが、今回はとりあえず上記 Issue で議論された内容で修正します。

参考: https://dev.to/lmillucci/building-a-vue-3-component-with-typescript-4pge

`shims-vue.d.ts` を修正します。
 
- before

``` JS 
  declare module "*.vue" {
    import Vue from "vue";
    export default Vue;
  }
```

- after

``` JS
  declare module "*.vue" {
    import { ComponentOptions } from "vue";
    const component: ComponentOptions
    export default component;
  }
```

compile エラーは無くなりました。

#### vue-loader

こちらはエラー内容から依存関係がうまくいっていないような気がしたため、そこに推測を立て、`yarn.lock` を確認しながら以下の方法で検証しました。

検証:

1. `"vue-cli-plugin-vue-next": "~0.1.3"`　を削除してインストールすると動く

- before: `yarn.lock`

``` JS 
"vue-loader-v16@npm:vue-loader@^16.0.0-beta.3", vue-loader@^16.0.0-alpha.3:
  name vue-loader-v16
  version "16.0.0-beta.5"
  resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.0.0-beta.5.tgz#04edc889492b03a445e7ac66e9226a70175ca8a0"
  integrity sha512-ciWfzNefqWlmzKznCWY9hl+fPP4KlQ0A9MtHbJ/8DpyY+dAM8gDrjufIdxwTgC4szE4EZC3A6ip/BbrqM84GqA==
  dependencies:
    "@types/mini-css-extract-plugin" "^0.9.1"
    chalk "^3.0.0"
    hash-sum "^2.0.0"
    loader-utils "^1.2.3"
    merge-source-map "^1.1.0"
    source-map "^0.6.1"
```

- after: `yarn.lock`

``` JS
"vue-loader-v16@npm:vue-loader@^16.0.0-beta.3", vue-loader@^16.0.0-alpha.3:
  version "16.0.0-beta.5"
  resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.0.0-beta.5.tgz#04edc889492b03a445e7ac66e9226a70175ca8a0"
  integrity sha512-ciWfzNefqWlmzKznCWY9hl+fPP4KlQ0A9MtHbJ/8DpyY+dAM8gDrjufIdxwTgC4szE4EZC3A6ip/BbrqM84GqA==
  dependencies:
    "@types/mini-css-extract-plugin" "^0.9.1"
    chalk "^3.0.0"
    hash-sum "^2.0.0"
    loader-utils "^1.2.3"
    merge-source-map "^1.1.0"
    source-map "^0.6.1"

```

2\. 別にもう一つプロジェクトを立ち上げて `yarn.lock` を削除、インストールして検証した結果、問題なく動いたためやはりうまく依存関係が解決できなかっただけかなと思います。
こちらに関して何かありましたらご意見ください。

#### vue-router

参考: https://github.com/vuejs/vue-router-next

`RouteConfig` は `RouteRecordRaw` に rename されるとあるので修正します。

- `src/router/index.ts`

``` JS
import { RouteRecordRaw, createRouter, createWebHistory } from "vue-router";
// 略

const routes: Array<RouteRecordRaw> = [
// 略

```

##### breaking changes の確認

- `mode: history` が `history` に変更されます。こちらは以下の通りインストール時点で変換されていました。

`src/router/index.ts`

``` JS
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
});
```

- 全ての route を示す `/*` はカスタム正規表現 `/:catchAll(.*)` を用いて宣言するようになるとのことなので、以下のように修正して確認します。

``` JS
const routes: Array<RouteRecordRaw> = [
  {
    path: "/:catchAll(.*)",
    name: "Home",
    component: Home
  },
];

```

`BASE_URL/asdf` 等　`asdf` 部分を良きように変えても `Home` component が表示されればOKです。

##### params の取り扱いについて

params が global な root を通す必要が無くなったため、どのように取得できるのか確認します。

- `/src/router/index.ts` に以下のように追記

``` JS
const routes: Array<RouteRecordRaw> = [
  {
    path: "/:catchAll(.*)",
    name: "Home",
    component: Home
  },
  {
    path: '/account/:id', component: Account // 追記
  },
  {
    path: "/about",
    name: "About",
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue")
  }
];

```

- `src/components/Account.vue` を作成

template 内では従来通りに取得できます。

``` JS
<template>
    {{ $route.params.id }}
</template>
```

setup 内では以下のようにして取得することができました。

``` JS
<script lang="ts">
import { defineComponent } from 'vue';
import { useRouter } from 'vue-router';
import router from '@/router'


export default defineComponent ({
    name: 'Account',
    setup(props, context){

       const { currentRoute }  = router
       console.log(currentRoute.value.params.id)
    }
})
</script>
```

ただ、こちらは検証不十分のため、ベストプラクティスかわからず...
近い内にもう少し掘り下げたいと思います。


#### Vuex

参考: https://github.com/vuejs/vuex/tree/4.0#vuex-4

breaking changes として、 Vuex のインストールプロセスが変更になり、 `createStore` 関数を使用することになった、とのことなので修正します。

- `src/store/index.ts`

``` JS
import { createStore } from "vuex";

export default createStore({
  state: {},
  mutations: {},
  actions: {},
  modules: {}
});
```

ここまでで compile エラーで出ていた箇所の修正は完了ですが、TS で使用する場合には独自にモジュール拡張を宣言する必要があるとのことなので、ドキュメント通りに修正しました。

- vuex-shim.d.ts

``` JS 
import { ComponentCustomProperties } from "vue";
import { Store } from "vuex";

declare module "@vue/runtime-core" {
  interface State {
  }

  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}
```

今回の breaking changes で、 Vue component 内でのグローバルな型付の削除が行われたため、完全に型付された構造を作ることができるようになりました。

debug をとって確かめるために、以下のように追加していきます。

- `vuex-shim.d.ts`

``` JS 
import { ComponentCustomProperties } from "vue";
import { Store } from "vuex";

declare module "@vue/runtime-core" {
  interface State {
    count: number;
  }

  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}
```

- `src/store/index.ts`

``` JS 
import { createStore } from "vuex";

export default createStore({
  state: {
    count: 1
  },
  mutations: {},
  actions: {},
  modules: {}
});
```

- `src/components/index.ts`

``` JS 
<script lang="ts">
import { defineComponent, SetupContext } from "vue";
import { useStore } from 'vuex';

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: String
  },
  setup() {
    const store = useStore()
    console.log(store.state.count) // 1 が表示される
  }
});
</script>
```

参考: https://blog.logrocket.com/whats-new-in-vuex-4/

以上となります。

## Epilogue

今回は Vue3 を実装する上でどこから手をつければいいのか把握する、を目標に実際に手を動かして検証してみました。次回は [vuejs/rfcs](https://github.com/vuejs/rfcs/tree/master/active-rfcs) を触りつつもう少し広げて作ってみようと思います。

また実際触ってみて global にする必要がなくなった、という点を忘れてしまいどこに格納されている or  どこから取得すればいいのか、と迷いましたが、スコープが小さくなったという点に気をつけ、Document を確認すれば特に困ることはあまりないのかな、と感じました。
ただ、Vue2 から Vue3 へ段階的に上げることができるのか、Vuex や vue-router の切替等、大きなプロジェクトの運用、進め方は やはり考慮しないといけないのか、と思います。

勉強途中のため、何かありましたらご連絡ください。

---
変更点: 
20/09/13: タイトル分かりにくいので修正しました