Closed13

Vite + Vue3で爆速開発のための準備の準備 #2 (eslint, Prettierを導入する)

satjopgsatjopg

なぜ入れるのか

現時点での私見です。

ESLint

  • 共通のルールのもとコーディングを行うことができ一定の品質を保つことができる(保っていることが言える)
    • ESLintのルール内でコードは書かれているため、チェックされる範囲でのバグがないことが保証される
  • 構文レベルでバグになるもの(なりそうなもの)をいち早く検知することができる
    • バグの発生件数が減る。
    • (個人的に)手戻りは萎えるので早め早めに検知しくれることはこの手戻りのステップを減少させてくれるので開発体験的にもよいものになる。(単体テストでも似たようなことが言える)
  • PRレビューで変更に対しての確認に集中することができる
    • 他の理由とほとんど重なっていますがESLintのルール内で書かれているので

Prettier

  • 個々人の勝手なルールでコードの整形を行わず統一することができる
    • ソースコードの見た目は「きれい」に保ちたいもの(もちろん中身もだけど)その「きれい」の基準をツール上で決めて自動で全体に適用させることができる
  • PRレビューで変更に対しての確認に集中することができる
    • ESLintでも同じこと書いていますが、ツールでチェック・直してくれるところは直してもらい本来の目的に注力することでレビューの質、コードの質を上げることが期待される。

もちろんこれをいれただけでは守られているかの保証はできない(ツールを使うかどうかが個人の勝手になってしまう)のでコードの変更時にチェック・整形が自動的に行われるようにすることは必要になる。

しかし、そもそもツールをいれないことには話にならないので兎にも角にも導入する。

satjopgsatjopg

ESLintの導入

eslintをインストール
eslintの初期設定をしてくれるコマンドが用意されているのでそれを呼び出します。

$ npm init @eslint/config

以下のように質問に答えると初期設定 + installを行ってくれる

質問に答える
$ npm init @eslint/config
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · vue
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · standard-with-typescript
✔ What format do you want your config file to be in? · YAML
Checking peerDependencies of eslint-config-standard-with-typescript@latest
The config that you've selected requires the following dependencies:

eslint-plugin-vue@latest eslint-config-standard-with-typescript@latest @typescript-eslint/eslint-plugin@^5.0.0 eslint@^8.0.1 eslint-plugin-import@^2.25.2 eslint-plugin-n@^15.0.0 eslint-plugin-promise@^6.0.0 typescript@*
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm
Installing eslint-plugin-vue@latest, eslint-config-standard-with-typescript@latest, @typescript-eslint/eslint-plugin@^5.0.0, eslint@^8.0.1, eslint-plugin-import@^2.25.2, eslint-plugin-n@^15.0.0, eslint-plugin-promise@^6.0.0, typescript@*

added 77 packages, and audited 244 packages in 5s

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

found 0 vulnerabilities
Successfully created .eslintrc.yml file in /Users/satjopg/development/satjopg/git/sample-vite-vue3-app
satjopgsatjopg

yamlファイルの中身は以下の通り
特に触れる点はなさそう。

yamlの中身

env:
browser: true
es2021: true
extends:

  • plugin:vue/vue3-essential
  • standard-with-typescript
    overrides: []
    parserOptions:
    ecmaVersion: latest
    sourceType: module
    plugins:
  • vue
    rules: {}

ESLintのルールに基づいてVSCodeの拡張をいれて設定

.vscode/settings.json
{
  "eslint.validate": ["html", "javascriptreact", "typescriptreact", "vue"]
}

ESLintを実行するためのコマンドを追加

package.json
{
  scripts: {
+    "lint": "eslint --ext .vue,.ts src/"
  }
}

実行する....怒られた

$ npm run lint

Oops! Something went wrong! :(

ESLint: 8.23.0

Error: Error while loading rule '@typescript-eslint/dot-notation': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
Occurred while linting /Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/main.ts
    at getParserServices (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/@typescript-eslint/utils/dist/eslint-utils/getParserServices.js:22:15)
    at create (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/@typescript-eslint/eslint-plugin/dist/rules/dot-notation.js:85:81)
    at Object.create (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/@typescript-eslint/utils/dist/eslint-utils/RuleCreator.js:41:20)
    at createRuleListeners (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/eslint/lib/linter/linter.js:922:21)
    at /Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/eslint/lib/linter/linter.js:1104:110
    at Array.forEach (<anonymous>)
    at runRules (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/eslint/lib/linter/linter.js:1041:34)
    at Linter._verifyWithoutProcessors (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/eslint/lib/linter/linter.js:1393:31)
    at Linter._verifyWithConfigArray (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/eslint/lib/linter/linter.js:1762:21)
    at Linter.verify (/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/node_modules/eslint/lib/linter/linter.js:1475:65)
satjopgsatjopg

公式ドキュメントや記事(本当にありがとうございます)を参考に設定を追加する

https://eslint.vuejs.org/user-guide/#installation
https://www.luku.work/vue3-ts-eslint-prettier

projectの追加については以下に記載されている
https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/README.md#parseroptionsproject

$ npm i -D @typescript-eslint/parser
.eslintrc.yml
env:
  browser: true
  es2021: true
extends:
  - plugin:vue/vue3-essential
  - standard-with-typescript
overrides: []
+ parser: 'vue-eslint-parser'
parserOptions:
+  parser: '@typescript-eslint/parser'
  ecmaVersion: latest
  sourceType: module
+  project: './tsconfig.json'
+  extraFileExtensions: ['.vue']
plugins:
  - vue
rules: {}

いざ実行

$ npm run lint

> sample-vite-vue3-app@0.0.0 lint
> eslint --ext .vue,.ts src/


/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/App.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/App.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/components/HelloWorld.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/components/HelloWorld.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/main.ts
  5:1  error  More than 1 blank line not allowed  no-multiple-empty-lines

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/pages/Login.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/pages/Login.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/pages/Top.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/pages/Top.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/router/index.ts
   1:60  error  Extra semicolon  @typescript-eslint/semi
   8:50  error  Extra semicolon  @typescript-eslint/semi
  10:17  error  Extra semicolon  @typescript-eslint/semi
  17:54  error  Extra semicolon  @typescript-eslint/semi
  18:19  error  Extra semicolon  @typescript-eslint/semi
  21:2   error  Extra semicolon  @typescript-eslint/semi
  26:3   error  Extra semicolon  @typescript-eslint/semi
  31:3   error  Extra semicolon  @typescript-eslint/semi
  33:22  error  Extra semicolon  @typescript-eslint/semi

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/vite-env.d.ts
  1:1  error  Do not use a triple slash reference for vite/client, use `import` style instead  @typescript-eslint/triple-slash-reference

✖ 15 problems (15 errors, 0 warnings)
  10 errors and 0 warnings potentially fixable with the `--fix` option.

しっかり怒られた。

satjopgsatjopg

vueファイルの箇所パースできないで怒られていた....

satjopgsatjopg

自動で直してくれるところは自動で直してもらいましょう

package.json
{
  scripts: {
    "lint:fix": "npm run lint -- --fix"
  }
}

実行。減りましたのでこれを直していく。

npm run lint:fix                                                                                         chapter/#2 ✗

> sample-vite-vue3-app@0.0.0 lint:fix
> npm run lint -- --fix


> sample-vite-vue3-app@0.0.0 lint
> eslint --ext .vue,.ts src/


/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/App.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/App.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/components/HelloWorld.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/components/HelloWorld.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/pages/Login.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/pages/Login.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/pages/Top.vue
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: src/pages/Top.vue.
The extension for the file (.vue) is non-standard. You should add "parserOptions.extraFileExtensions" to your config

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/vite-env.d.ts
  1:1  error  Do not use a triple slash reference for vite/client, use `import` style instead  @typescript-eslint/triple-slash-reference

✖ 5 problems (5 errors, 0 warnings)
satjopgsatjopg

vueファイルパースできないで怒られていたので直す。
よく見たら答えは書いてありました。

.eslintrc.yml
env:
  browser: true
  es2021: true
extends:
  - plugin:vue/vue3-essential
  - standard-with-typescript
overrides: []
parser: 'vue-eslint-parser'
parserOptions:
  parser: '@typescript-eslint/parser'
  ecmaVersion: latest
  sourceType: module
  project: './tsconfig.json'
+ extraFileExtensions: ['.vue']
plugins:
  - vue
rules: {}

実行、エラー内容が見れました。

npm run lint:fix                                                                                         chapter/#2 ✗

> sample-vite-vue3-app@0.0.0 lint:fix
> npm run lint -- --fix


> sample-vite-vue3-app@0.0.0 lint
> eslint --ext .vue,.ts src/


/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/pages/Login.vue
  1:1  error  Component name "Login" should always be multi-word  vue/multi-word-component-names

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/pages/Top.vue
  1:1  error  Component name "Top" should always be multi-word  vue/multi-word-component-names

/Users/satjopg/development/satjopg/git/sample-vite-vue3-app/src/vite-env.d.ts
  1:1  error  Do not use a triple slash reference for vite/client, use `import` style instead  @typescript-eslint/triple-slash-reference

✖ 3 problems (3 errors, 0 warnings)
satjopgsatjopg

importに変えろと怒られていたけど、そのimportされたものを明示して使う箇所がなく
泣く泣く例外にした。

vite-env.d.ts
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference types="vite/client" />

ほかはComponentの命名はマルチワードにせよ、ということなので
pages配下のコンポーネントはXXXXPage.vueに変更。

routerのimport箇所を直す (自動で直してくれなかったので)

router.ts
const routes = [
  {
    path: '/',
    name: 'top',
    component: async () => {
-      const top = await import('@/pages/Top.vue')
+      const top = await import('@/pages/TopPage.vue')
      return top
    }
  },
  {
    path: '/login',
    name: 'login',
    component: async () => {
-      const login = await import('@/pages/Login.vue')
+      const login = await import('@/pages/LoginPage.vue')
      return login
    }
  }
]

再実行, 問題なくなる。

$ npm run lint

> sample-vite-vue3-app@0.0.0 lint
> eslint --ext .vue,.ts src/
(何も出力されない)
satjopgsatjopg

prettierをいれる

$ npm install -D prettier @vue/eslint-config-prettier

.prettierc を設定する
ここはプロジェクトごとに設定すれば良いのでとりあえず。

.prettierc
{
  // 1行120文字まで
  "printWidth": 120,
  // tabは空白2つ分
  "tabWidth": 2,
  // 文字列はシングルクウォートにする
  "singleQuote": true,
  // 末尾のカンマは設定しない
  "trailingComma": "none",
  // 行末はセミコロン
  "semi": true
}

package.jsonに実行用コマンドを追加し実行

package.json
{
  "scripts": {
    "format": "prettier -w src/*.{ts,vue} && prettier -w src/**/*.{ts,vue}"
  }
}
$ npm run format

> sample-vite-vue3-app@0.0.0 format
> prettier -w src/*.{ts,vue} && prettier -w src/**/*.{ts,vue}

src/main.ts 171ms
src/vite-env.d.ts 5ms
src/App.vue 14ms
src/router/index.ts 178ms
src/components/HelloWorld.vue 55ms
src/pages/LoginPage.vue 6ms
src/pages/TopPage.vue 2ms

これにて導入完了

satjopgsatjopg

VSCodeの設定を追加して自動でフォーマットされるようにする
こちらの記事を参考にさせていただきました!
とてもわかりやすかったです、ありがとうございます!
https://qiita.com/fukasawah/items/03fa205353ac03b06b7e

.vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "[vue]": {
      "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "[javascript]": {
      "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "[typescript]": {
      "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "editor.formatOnSave": true
}

保存時に整形されるようになりました。

このスクラップは2022/09/10にクローズされました