ESLintを導入してみました

## 背景
JavaScriptをこれから書いていくので、その前にJavaScript用の[ESLint](https://eslint.org/)
を導入したいと思います。。


## 環境
```
rails 6.1.4.1

jsbundling-rails (1.2.1)
cssbundling-rails (1.3.3)
tailwindcss-rails (2.0.32)

❯ yarn --version
1.22.19

"esbuild": "^0.17.18"
```
## eslint-rails
[appfolio/eslint\-rails](https://github.com/appfolio/eslint-rails)はアーカイブされていたため、使用しません。

## 導入手順
### 1. インストール
```
yarn add eslint --dev
```

### 2. 設定ファイルを選ぶ（ベース）
- [eslint\-config\-\* の比較表](https://zenn.dev/tapioca/articles/5685d794f6452b)

`eslint-config-airbnb-base`を採用した

### 3.1 設定ファイルを追加
```bash
❯ yarn add eslint-config-airbnb-base --dev
yarn add v1.22.19
[1/4] 🔍  Resolving packages...
⠂ eslint-config-airbnb-base(node:50766) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > eslint-config-airbnb-base@15.0.0" has unmet peer dependency "eslint-plugin-import@^2.25.2".
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
success Saved 41 new dependencies.
info Direct dependencies
└─ eslint-config-airbnb-base@15.0.0
info All dependencies
├─ arraybuffer.prototype.slice@1.0.2
├─ confusing-browser-globals@1.0.11
├─ es-set-tostringtag@2.0.2
├─ es-to-primitive@1.2.1
├─ eslint-config-airbnb-base@15.0.0
├─ function.prototype.name@1.1.6
├─ get-intrinsic@1.2.2
├─ get-symbol-description@1.0.0
├─ globalthis@1.0.3
├─ has-bigints@1.0.2
├─ internal-slot@1.0.6
├─ is-bigint@1.0.4
├─ is-boolean-object@1.1.2
├─ is-callable@1.2.7
├─ is-date-object@1.0.5
├─ is-negative-zero@2.0.2
├─ is-number-object@1.0.7
├─ is-string@1.0.7
├─ is-symbol@1.0.4
├─ is-typed-array@1.1.12
├─ is-weakref@1.0.2
├─ isarray@2.0.5
├─ object-inspect@1.13.1
├─ object.assign@4.1.4
├─ object.entries@1.1.7
├─ regexp.prototype.flags@1.5.1
├─ safe-array-concat@1.0.1
├─ safe-regex-test@1.0.0
├─ set-function-length@1.1.1
├─ set-function-name@2.0.1
├─ side-channel@1.0.4
├─ string.prototype.trim@1.2.8
├─ string.prototype.trimend@1.0.7
├─ string.prototype.trimstart@1.0.7
├─ typed-array-buffer@1.0.0
├─ typed-array-byte-length@1.0.0
├─ typed-array-byte-offset@1.0.0
├─ typed-array-length@1.0.4
├─ unbox-primitive@1.0.2
├─ which-boxed-primitive@1.0.2
└─ which-typed-array@1.1.13
✨  Done in 3.72s.
```


### 4. ESLintの初期設定
```bash
❯ yarn eslint --init
yarn run v1.22.19
$ /Users/xxx/rfs/node_modules/.bin/eslint --init
You can also run this command directly using 'npm init @eslint/config'.
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript
Successfully created .eslintrc.js file in /Users/xxx/rfs
✨  Done in 57.58s.
```

### 問題
```bash
❯ yarn lint
yarn run v1.22.19
$ eslint app/javascript/**/*

Oops! Something went wrong! :(

ESLint: 8.53.0

ESLint couldn't find the plugin "eslint-plugin-import".

(The package "eslint-plugin-import" was not found when loaded as a Node module from the directory "/Users/xxx/rfs".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

    npm install eslint-plugin-import@latest --save-dev

The plugin "eslint-plugin-import" was referenced from the config file in ".eslintrc.js » eslint-config-airbnb-base » /Users/xxx/rfs/node_modules/eslint-config-airbnb-base/rules/imports.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

3.1では手動で`eslint-config-airbnb-base`を追加したため、↑に依存関係のエラーが発生しました。

### 3.2 設定ファイルを再度追加

```bash
❯ npx install-peerdeps --dev eslint-config-airbnb-base

install-peerdeps v3.0.3
It seems as if you are using Yarn. Would you like to use Yarn for the installation? (y/n) y
Installing peerdeps for eslint-config-airbnb-base@latest.
yarn add eslint-config-airbnb-base@15.0.0 eslint@^8.2.0 eslint-plugin-import@^2.25.2 --dev

SUCCESS eslint-config-airbnb-base
  and its peerDeps were installed successfully.
```

- install-peerdeps
  - install an NPM package and its peer dependencies automatically

## 実行
### ビルドに追加（package.json）
```json
  "scripts": {
    "lint": "eslint app/javascript/**/*",
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets",
    "build:css": "tailwindcss --postcss -c ./config/tailwind.config.js -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css"
  }
```

### RUN
```bash
❯ yarn lint
yarn run v1.22.19
$ eslint app/javascript/**/*

省略...
```

### 自動修正
```bash
❯ yarn lint --fix
yarn run v1.22.19
$ eslint app/javascript/**/* --fix

省略...
```

### 手動対応
自動修正できない部分については、手動で対応していきます。

## 参照
- [Getting Started with ESLint \- ESLint \- Pluggable JavaScript Linter](https://eslint.org/docs/latest/use/getting-started)
- [eslint\-config\-\* の比較表](https://zenn.dev/tapioca/articles/5685d794f6452b)
- [【ESLint】個人テンプレートのESLintを改善するためにeslint\-config\-airbnbを調査してみる](https://zenn.dev/shuuuuuun/articles/127728961f89a0)
- [appfolio/eslint\-rails](https://github.com/appfolio/eslint-rails)