かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Vite + React (TypeScript) のプロジェクトに ESLint と Prettier を導入する。

前回までのあらすじ

Vite で React (TypeScript) のプロジェクトを作ってパスエイリアスの設定をいい感じにしました
今回はいつもの ESLint と Prettier を導入します。(ホントいつもの…)
結論から言えば VIte だからという事は特になく、create-react-app で作成したプロジェクトと大差ありませんでした

ESLint

パッケージのインストール

$ npm i -D eslint eslint-plugin-react-hooks

React のドキュメントに Hooks の呼び出し場所をコンポーネントとカスタムフック内に強制できる eslint-plugin-react-hooks について書かれていたので合わせて導入しました

ESLint の設定を作成

CLI で作成します

$ npx eslint --init
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now with npm?   Yes
ESLint の module type を何にすべきか?
? What type of modules does your project use? (Use arrow keys)
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

ESLint でプロジェクトの使っている module タイプの指定があります。Vite で作成された tsconfig.jsontarget: "ESNext", "module": "ESNext" となっているので、JavaScript modules (ESM) か None of these か迷いました。

tsconfig の module と target
  • targetコンパイル時にどのバージョンの JavaScript で出力するか
  • module … 出力されるJavaScriptがどのようにモジュールを読み込むか

module
es2015, es2020, esnext 通称 esmodule と呼ばれるモジュール読み込みの解決方法です。フロントエンドで使われています。Node.jsは13.2.0でバックエンドでも同様にこのモジュール解決方法をサポートしましたが2020年現在は対応しているパッケージは少ないです。
cf. tsconfig.jsonを設定する | TypeScript入門『サバイバルTypeScript』

tsconfig の module の ESNextesmodule の方法だとあったので ESLInt の What type of modules does your project use? の質問は JavaScript modules (import/export) を選択しました。
少し自信がないので、間違っていたら指摘いただきたいです :pray:

eslint-plugin-react-hooks の設定を追加

.eslintrc.js

module.exports = {
  "plugins": [
    // ...
+   "react-hooks"
  ],
  "rules": {
    // ...
+   "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
+   "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}

import react from 'React' がない場合もエラーにならないルールを追加

React 17 から不要になっているが、ESLint がエラーになってしまうので

.eslintrc.js

module.exports = {
  // ...
  rules: {
    // ...
+   'react/react-in-jsx-scope': 'off',
  }
}

後はお好みでルールを追加すれば OK

Prettier

こちらも特に Vite だからという違いはなさそうです

$ npm i -D prettier eslint-config-prettier
# 設定ファイルの作成
$ touch .prettierrc.json

フォーマットの設定

.prettierrc.json

{
  "trailingComma": "all",
  "tabWidth": 2,
  "printWidth": 80,
  "singleQuote": true,
  "jsxSingleQuote": true,
  "arrowParens": "always",
  "bracketSpacing": true,
  "jsxBracketSameLine": false,
  "semi": true,
  "endOfLine": "lf"
}

※ お好みで

ESLint と連携

.eslintrc.js

{
  "extends": [
    //...
+   "prettier"
  ]
}

ESLint と Prettier 用の npm scripts を作成

package.json

{
  // ...
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
+   "lint": "eslint --ext .js,.jsx,.ts,.tsx src/",
+   "lint:fix": "npm run lint -- --fix",
+   "format": "npm run lint:fix && prettier --write 'src/**/*.{js,jsx,ts,tsx}'"
  },

使ってない import を自動で削除する

eslint-plugin-unused-imports

$ npm i -D eslint-plugin-unused-imports

.eslintrc.js

{
  "plugins": [
    "react",
    "@typescript-eslint",
+   "unused-imports"
  ],
  "rules": {
+   "@typescript-eslint/no-unused-vars": "off", // or "no-unused-vars": "off",
+   "unused-imports/no-unused-imports": "error",
+   "unused-imports/no-unused-vars": [
+     "warn",
+     { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
+   ]
  }
}

import の順番を自動でいい感じにする

eslint-plugin-import

$ npm i -D eslint-plugin-import

.eslintrc.js

{
  "plugins": [
    "react",
    "@typescript-eslint",
    "unused-imports",
+   "import"
  ],
  "rules": {
    // … 
    // import の順番の設定
+   "import/order": []
  }
}

順番の指定方法は eslint-plugin-import の Wikiを参考に下記のようにしてみました。

{
  rules: {
    'import/order': [
      'error',
      {
        // グループの順番
        groups: [
          'builtin',
          'external',
          'internal',
          ['parent', 'sibling'],
          'object',
          'type',
          'index',
        ],
        // グループ感に空行追加しない
        'newlines-between': 'never',
        pathGroupsExcludedImportTypes: ['builtin'],
        // ABC 順。大文字小文字を区別しない
        alphabetize: { order: 'asc', caseInsensitive: true },
        pathGroups: [
          // react 関連を先頭に
          {
            pattern: 'react**',
            group: 'external',
            position: 'before',
          },
          {
            pattern: '{@/libs/**,@/features/**,@/app/**}',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '{@/components/**,@/pages/**}',
            group: 'internal',
            position: 'before',
          },
          // css modules は一番最後にする
          {
            pattern: './**.module.css',
            group: 'index',
            position: 'after',
          },
        ],
      },
    ]
  }
}

所感

ESLInt, Prettier 共に Vite だからという違いは特にありませんでした。
新しくプロジェクト作る度にこの辺り調べてやり直してる気がする…

今回はやっている中で npm install の際に --save-exact オプションを使うと ^10.0.0 のような 10.0.0 以上ではなく 10.0.0 とインスールするバージョンが完全に固定できるということを知りることができました! 毎回やってるけど何かしら発見あるからよし!(永遠の初心者)

おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]

O'Reillyの読んだらブルーベリー本買うんだ…

もうネタがプロジェクトキレイキレイしか思いつかねぇ…