【Vue3】Vite+Vue3+TypeScript+ESLint+Prettier+TailwindCSSでの環境構築【2022年11月版】

## はじめに

最近はNuxt3で何かしようと思っていろいろやってましたが、普通の静的サイトを作る分にはただのVueで十分だとわかったのでVueでやり直そうと思いました。<br>
……が、意外と環境構築で戸惑ったので備忘録として残します。

## 環境

```:環境
VSCode: v1.72.2
yarn: v1.22.18

"vue": "^3.2.41"

"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"@vitejs/plugin-vue": "^3.2.0",
"autoprefixer": "^10.4.13",
"eslint": "^8.26.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-tailwindcss": "^3.6.2",
"eslint-plugin-vue": "^9.6.0",
"postcss": "^8.4.18",
"prettier": "^2.7.1",
"prettier-plugin-tailwindcss": "^0.1.13",
"tailwindcss": "^3.2.1",
"typescript": "^4.6.4",
"vite": "^3.2.0",
"vue-tsc": "^1.0.9"
```

## 導入

### Vite

今回作成するプロジェクト名はvue-sampleとする

```bash
$ yarn create vite vue-sample
```

```bash
? 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.
    JavaScript
❯   TypeScript
    Customize with create-vue ↗
    Nuxt ↗
```

完了したら、

```bash
$ yarn install
```

### Take Over Modeを有効化

VSCodeの拡張機能のタブの検索欄に`@builtin typescript`と入力
すると`TypeScript と JavaScript の言語機能`というものが出てくるので`無効にする(ワークスペース)`を選択

### TailwindCSS

以下をインストール

```bash
$ yarn add -D tailwindcss postcss autoprefixer
```

以下をroot階層(vite.config.tsと同じ位置)に作成

```js:tailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

```js:postcss.config.cjs
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

ここで注意するのがファイル名を`tailwind.config.cjs`や`postcss.config.cjs`にすること(拡張子`cjs`が重要)
こうしないと
`tailwind.config.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules. ~`
といったエラーが発生する場合がある

次に、style.cssを以下に書き換える

```css:style.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

### ESLint & Prettier

以下をインストール

```bash
$ yarn add -D eslint eslint-config-prettier eslint-plugin-tailwindcss eslint-plugin-vue @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier prettier-plugin-tailwindcss
```

以下をroot階層に作成

```json:.eslintrc.json
{
  "root": true,
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-recommended",
    "plugin:vue/essential",
    "plugin:tailwindcss/recommended",
    "prettier"
  ],
  "overrides": [],
  "parserOptions": {
    "parser": "@typescript-eslint/parser",
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": ["vue", "@typescript-eslint", "tailwindcss"]
}
```

```:.prettierrc
{
  "singleQuote": true,
  "semi": true,
  "vueIndentScriptAndStyle": true,
  "extends": [
    "plugin:vue/vue3-recommended",
    "eslint:recommended",
    "@vue/typescript/recommended",
    "@vue/eslint-config-prettier"
  ]
}
```

特に`.eslintrc.json`の`extends`の順番に注意する
`"plugin:@typescript-eslint/recommended"`は上の方に書いてあったほうが無難な気がする

### tsconfig.json

TypeScriptの制約を強くしたい人は`tsconfig.json`に以下を追記

```:tsconfig.json
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
```

さらにこれも追記

```:tsconfig.json
    "baseUrl": "./",
    "paths": {
      "~~": ["."],
      "~~/*": ["./*"],
      "@@": ["."],
      "@@/*": ["./*"],
      "~": ["src"],
      "~/*": ["src/*"],
      "@": ["src"],
      "@/*": ["src/*"],
      "assets": ["src/assets"],
      "assets/*": ["src/assets/*"]
    },
```

最終的にはこれ

```json:tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "baseUrl": "./",
    "paths": {
      "~~": ["."],
      "~~/*": ["./*"],
      "@@": ["."],
      "@@/*": ["./*"],
      "~": ["src"],
      "~/*": ["src/*"],
      "@": ["src"],
      "@/*": ["src/*"],
      "assets": ["src/assets"],
      "assets/*": ["src/assets/*"]
    },
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
```

**11/21追記**
pathのaliasを反映させるには`vite.config.ts`の設定も必要でした。

```typescript:vite.config.ts
import { defineConfig } from 'vite';

import vue from '@vitejs/plugin-vue';

// https://vitejs.dev/config/
export default defineConfig({
  server: {
    host: true,
  },
  plugins: [vue()],
  resolve: {
    alias: {
      '~~': `${__dirname}/`,
      '~~/': `${__dirname}/`,
      '@@': `${__dirname}/`,
      '@@/': `${__dirname}/`,
      '~': `${__dirname}/src/`,
      '~/': `${__dirname}/src/`,
      '@': `${__dirname}/src/`,
      '@/': `${__dirname}/src/`,
      assets: `${__dirname}/src/assets/`,
      'assets/': `${__dirname}/src/assets/`,
    },
  },
});
```

また、`__dirname`を使用しているので型定義もインストール。

```bash
$ yarn add -D @types/node
```


## おわりに

ESLint周りはいつも謎のエラーを吐くことが多いのでややこしい。
ESLintで沼ったらウィンドウの再読み込みで治る場合があります。