Vuetify3 + Vite プロジェクトの作成

# 概要

備忘録も兼ねて,Vuetifyのプロジェクトの作成方法や開発に必要な設定を記載します.

## 目次

- [概要](#概要)
  - [目次](#目次)
  - [動作環境](#動作環境)
  - [拡張機能の追加](#拡張機能の追加)
  - [Vueプロジェクトの作成](#vueプロジェクトの作成)
  - [Vuetifyの導入](#vuetifyの導入)
    - [パッケージの追加](#パッケージの追加)
    - [vuetify.tsの作成](#vuetifytsの作成)
    - [Could not find a declaration file for module 'vuetify/components' エラーの対応](#could-not-find-a-declaration-file-for-module-vuetifycomponents-エラーの対応)
    - [main.jsの修正](#mainjsの修正)
    - [Vuetifyが適応されたかどうか確認](#vuetifyが適応されたかどうか確認)
  - [マテリアルアイコン利用する場合](#マテリアルアイコン利用する場合)
  - [settings.jsonの設定](#settingsjsonの設定)
  - [参考](#参考)

## 動作環境

- Windows 11
- node v18.12.1
- npm 8.19.2
- powershell

## 拡張機能の追加

以下の拡張機能をVSCodeに追加します.

- Vue Language Features (Volar)
- TypeScript Vue Plugin (Volar)
- Prettier - Code formatter

## Vueプロジェクトの作成

始めにVueプロジェクトをViteから作成します.

プロジェクト作成時にルータを入れたかったのでカスタム設定しています.

選択項目ではEnd-to-End Testing以外はYesで設定しました.

```powershell
PS C:~vuetify> npm create vite
√ Project name: ... vuetify-project
? Select a framework: » - Use arrow-keys. Return to submit.
    Vanilla
>   Vue
    React
    Preact
    Lit
    Svelte
    Others
? Select a variant: » - Use arrow-keys. Return to submit.
    TypeScript
    JavaScript
>   Customize with create-vue ↗
    Nuxt ↗

Vue.js - The Progressive JavaScript Framework

√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
√ Add Prettier for code formatting? ... No / Yes
```

プロジェクトディレクトリに移動し,以下コマンドから問題なく起動できるか確認します.

```powershell
npm install
npm run dev
```

![start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357884/eea3d825-f8c3-a883-cac0-6162e753a453.png)


## Vuetifyの導入

### パッケージの追加

npm install でVuetifyを追加します.

```powershell
PS C:~\vuetify-project> npm install vuetify

added 1 package, and audited 478 packages in 6s

112 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

### vuetify.tsの作成

[公式ドキュメント]("https://vuetifyjs.com/en/getting-started/installation/")に沿ってpluginsに以下のvuetify.tsを追加します.

pluginsフォルダは作成されていないのでsrc直下に作成します.

```TypeScript
// /src/plugins/vuetify.ts
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

export default createVuetify({
  components,
  directives,
})
```

### Could not find a declaration file for module 'vuetify/components' エラーの対応

Vuetifyの型定義ファイルがないため,以下のようにエラーが発生します.

tsconfigにVuetifyの記載を追加することで解消するようなので,tsconfigを編集します.

参考：[TypeScript + Vuetifyでエラー「Could not find a declaration file for module 'vuetify/lib'. 」したときの対処法](https://scrapbox.io/nwtgck/TypeScript_+_Vuetify%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E3%80%8CCould_not_find_a_declaration_file_for_module_'vuetify%2Flib'._%E3%80%8D%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95)

![declaration_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357884/0adb84cf-ce22-c470-697d-d896bee231e4.png)


プロジェクトルートにtsconfig.vuetify.jsonを作成します.

※設定項目が不明だったので,vue createで作成した別プロジェクトからtsconfig.jsonの内容を持ってきました.

```TypeScript
// tsconfig.vuetify.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "moduleResolution": "node",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "useDefineForClassFields": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": ["vuetify"],
    "paths": {
      "@/*": ["src/*"]
    },
    "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
  "exclude": ["node_modules"]
}
```

tsconfig.jsonにtsconfig.vuetify.jsonの記載を追加します.

```TypeScript
// tsconfig.json
{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.node.json"
    },
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.vitest.json"
    },
    // 以下を追加
    {
      "path": "./tsconfig.vuetify.json"
    }
  ]
}
```

### main.jsの修正

main.jsにVuetifyに関する設定を追加します.

```TypeScript
import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'
import vuetify from './plugins/vuetify' // 追加

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.use(vuetify) // 追加

app.mount('#app')
```

### Vuetifyが適応されたかどうか確認

App.vueにVuetifyのコードを記載し,実際に動くか見てみます.

以下はApp.vueにボタンのみ設置した場合です.

```vue
<template>
  <v-btn block rounded="0" size="x-large">Test Button</v-btn>
</template>
```

以下の通り,Vuetifyが適応されていることが確認できました.

![setting-ok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357884/753c3b69-c5a2-c832-6f3a-fbc02637d5a0.png)


適応されていない場合はボタンが表示されません.

![setting-ng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357884/a68a53a4-250b-1cc4-5a2a-3784a2ad74f1.png)


## マテリアルアイコンを利用する場合

マテリアルアイコンを利用する際は以下のようにvuetify.tsを変更します.

参考:[Icon Fonts](https://vuetifyjs.com/en/features/icon-fonts/)

```TypeScript
// vuetify.ts
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import { aliases, mdi } from 'vuetify/iconsets/mdi'
import '@mdi/font/css/materialdesignicons.css'

export default createVuetify({
  components,
  directives,
  icons: {
    defaultSet: 'mdi',
    aliases,
    sets: {
      mdi,
    }
  },
})

```

アイコンのinstallもしておきます.

```powershell
npm install @mdi/font -D
```

以下のようにApp.vueを書き換え,アイコンが表示されるか確認します.

```Vue
// App.vue
<template>
  <v-icon icon="mdi-home" />
</template>
```

設定できていれば以下のようにアイコンが表示されます.

設定できていない場合は何も表示されません.

![icon-ok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357884/4cd805b7-6946-c1a0-bfab-3327f027b387.png)


## settings.jsonの設定

保存時に自動的に修正してほしいので,formatterの設定をsettings.jsonに記載します.

```json
// .vscode/settings.json
{
  "cSpell.words": ["iconsets", "materialdesignicons", "pinia", "vuetify"],
  "editor.defaultFormatter": "esbenp.prettier-vscode", 
  "editor.formatOnSave": true
}
```

## 参考

- [Vuetify公式](https://vuetifyjs.com/en/getting-started/installation/)
- [TypeScript + Vuetifyでエラー「Could not find a declaration file for module 'vuetify/lib'. 」したときの対処法](https://scrapbox.io/nwtgck/TypeScript_+_Vuetify%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E3%80%8CCould_not_find_a_declaration_file_for_module_'vuetify%2Flib'._%E3%80%8D%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95)
- [【Vue.js】Vuetify と TypeScript を使用した環境を構築してサンプルプロジェクトを立ち上げるまでの手順](https://qiita.com/Nossa/items/3860e55551697bb46e38#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BF%AE%E6%AD%A3)
- [既存のVue3プロジェクトにVuetify3を導入する](https://qiita.com/kuro_sabo10/items/cc497f26c1b8456f0296)