ESLintでimport自動整形に関して　ESLint × Prettierの設定しているなら「なし」に落ち着く予感

## はじめに
自身が開発しているプロジェクト内で少し議論になった事もあり、importの自動整形についてはどうなのか？考えてみた。

（プロジェクトや個人の考え方に結局よると事だが）なんとなく結論としては、ESLint・Prettierの構成を取っているなら、スタイルの修正をESLintで行わせる事になるimportの自動整形は「なし」になるだろうなと思う。

以下では、ESLint・Prettierの構成の場合に、なぜimportの自動整形が「なし」になりそうか？についてみていきつつ、ESLintの静的解析とPrettierのコード整形を分離する方法についても見ていく。
おまけとして、「なし」といったもののやりたいという需要もあると思われるので、importの自動整形を行う方法についても取り上げた。

## importの自動整形はできるけど、ESLint × Prettierのプロジェクトではやらない、になるだろう
Javascript（Node.js）であれば、静的解析にESLint、コードフォーマッターにPrettier、という構成は鉄板だと思う。その場合、importの自動整形ってどうなの？について考えてみたい。

[Integrating with Linters](https://prettier.io/docs/en/integrating-with-linters.html)に書かれている通り、Prettierとしては基本的にはESLintとPrettierは分けて使われるべき（コードのスタリングに関してはPrettierが担うべきでESLintがスタイル以外の静的解析に専念すべし）という考え方をしている。

> ・You end up with a lot of red squiggly lines in your editor, which gets annoying. Prettier is supposed to make you forget about formatting – and not be in your face about it!（エディタに赤いジグザグ線がたくさん表示され、イライラしてしまいます。Prettierは書式設定のことを忘れさせてくれるものであり、また、書式設定に煩わされないものです）
・They are slower than running Prettier directly.（直接Prettierを動かすより遅い）
・They’re yet one layer of indirection where things may break.（このように、物事が壊れる可能性のある間接的なレイヤーがまだ1つあるのです）

つまり、ESLintの設定の実装的な話で言えば、ESLintが持つスタイルに関するルールは[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)を使いoffにし、スタイルに関してPrettierと衝突するような状態を避けるように設定した上で、Prettierのコマンド（`prettier --write`）でフォーマッティングする、という考え方をしている。

という事は…、今回取り上げているimportの自動整形についてはコードのスタイルに関する話なのでESLintでやるのはPrettierの思想的にはNGになるので、結論としてimportの自動整形は「なし」に落ち着く気がする（[ESLintとprettier](https://note.com/shift_tech/n/n8bbe1c05ba0b#ESLint%E3%81%A8prettier)も参照）。

※ちなみに、ESLintの方でも[sort-import does not auto fix #11542](https://github.com/eslint/eslint/issues/11542)で議論されているように、importの自動整形はしないと決めているようである。詳細は[sort-importsのルールではeslint --fixが効かない！？](#sort-importsのルールではeslint---fixが効かない)を参照）

※ESLintのルールにPrettierのコードスタイルのルールを組み込み、コードのスタイルも静的解析でエラーにさせる方法も実はあり、それについては[prettier について](https://note.com/shift_tech/n/n8bbe1c05ba0b#efd459c9-42b2-4432-b5ce-72431dc024d2)を参照。ただし、PrettierのルールをESLintに組み込まずとも、[Git hooks](https://prettier.io/docs/en/install.html#git-hooks)（simple-git-hooks）などを使う事でgit commitなどのタイミングで自動整形を走らせる事はできるので、ESLintにPrettierのルールを組み込む必然性はない（Git hooksでコードフォーマッターが動くのであれば、エディターの差やコマンドの実行し忘れなども防げるので）。

### Prettierが推奨する設定の例として
上記で見てきたように、スタイルに関する部分はPrettierに全て任せるようにするには以下のように`.eslintrc.json`を設定すればいい。

```bash
$ yarn add --dev eslint-config-prettier
```
```json:.eslintrc.json
{
	...
	"extends": [
		...
		"prettier" // <- extendsの末尾に記載するのがポイント
	],
	...
}
```

このようにする事で、Prettierのスタイルルールと衝突するルールをOffにし、ESLintのチェックでコードのスタイルに関するエラーが出なくなる。
ちなみに、コードのスタイルに関するエラーが出ている状態の例としては以下の画像のようなイメージで、これがPrettierが

> You end up with a lot of red squiggly lines in your editor, which gets annoying. Prettier is supposed to make you forget about formatting – and not be in your face about it!（エディタに赤いジグザグ線がたくさん表示され、イライラしてしまいます。Prettierは書式設定のことを忘れさせてくれるものであり、また、書式設定に煩わされないものです）

と言っている事（詳細は[prettier について](https://note.com/shift_tech/n/n8bbe1c05ba0b#efd459c9-42b2-4432-b5ce-72431dc024d2)を参照）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/b93b515e-7e4b-438f-90e8-dc148e8cefa6.png)

ソースコード全体は以下。

https://github.com/yuta-katayama-23/node-express/blob/929ea5ef3e5e027c5f30b58f4d03ee9d6c09760d/.eslintrc.json

※Prettierの推奨設定を行う方法については、[ESLint・Prettierを併用してコードスタイルのチェックはPrettierにまかせてみた](https://note.com/shift_tech/n/n2a0b5561c27b)などの記事も参考になる。

## まとめとして
上記で見てきたように、importの自動整形はやらないという感じになりそうだな～と思う。
とは言えやりたいという場合には、以下の[おまけ](#おまけ)にあるような方法でimportの自動整形をする事は可能。

## おまけ
### ESLintのルール`sort-imports`でimportの順番をエラー表示する
`.eslintrc.json`に以下のように`sort-imports`を記載するだけ。

```json:.eslintrc.json
{
	...
	"rules": {
		...
		"sort-imports": "warn"
	},
	...
}
```


ソースコード全体は以下。

https://github.com/yuta-katayama-23/node-express/commit/21fee2410c90b4a71ba94a22bd3ce88dc51db5e2

実際にESLintをかけてみると…

```console
[root@localhost node-express]# npx eslint .

/root/workspace/node-express/src/middleware/custome-openapi-validator.js
  3:1  error  Imports should be sorted alphabetically       sort-imports
  4:1  error  Expected 'all' syntax before 'single' syntax  sort-imports

✖ 2 problems (2 errors, 0 warnings)
```

のようにエラーが表示される（VS CodeでESLintのExtensionが入っていれば以下の画像のようにエラーが図示される）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/34f80ac9-3dd0-0083-40f8-0901d4c9db0e.png)

※ESLintのルール設定方法は[Configuring Rules](https://eslint.org/docs/user-guide/configuring/rules#configuring-rules)に書かれている通りで、上記ではerrorになるように設定いるが、warnにしたりもできる。warnに設定すると以下のようになる。

```console
[root@localhost node-express]# npx eslint .

/root/workspace/node-express/src/middleware/custome-openapi-validator.js
  3:1  warning  Imports should be sorted alphabetically       sort-imports
  4:1  warning  Expected 'all' syntax before 'single' syntax  sort-imports

✖ 2 problems (0 errors, 2 warnings)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/5aa022be-e015-1344-d844-41aab64e8a5c.png)

※ちなみに、`sort-imports`のルールは、よくESLintの設定で行うであろう`"extends": [ eslint:recommended ]`には含まれていないので、自分で手動で追加するか、全てのルールを継承する`eslint:all`を設定する必要がある。ESLintのextendsについては[extends](https://note.com/shift_tech/n/n8bbe1c05ba0b#extends)を参照。

### `sort-imports`のルールでは`eslint --fix`が効かない！？
[sort-imports](https://eslint.org/docs/rules/sort-imports)にも

> The --fix option on the command line can automatically fix some of the problems reported by this rule.（コマンドラインの-fixオプションは、このルールで報告された問題のいくつかを自動的に修正することができます）

と書かれているし、[RulesのSuggestionsの項](https://eslint.org/docs/rules/#suggestions)に、以下の図の通り`fixable`となっているので自動で修正されそうな気がする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/a9ebc8d6-cfdc-ba29-55e1-248fe7094ef5.png)

が、[sort-import does not auto fix #11542](https://github.com/eslint/eslint/issues/11542)で議論されているように、

> However, I don't think it would be safe for sort-imports to autofix code because it could change the evaluation order of the imported modules, which could unexpectedly affect how the code works.（sort-importによるコードの自動修正は、インポートされたモジュールの評価順序を変更し、コードの動作に予期せぬ影響を与える可能性があるため、安全とは言えないと考えています）

との事なので、自動で修正はされないという事になっている。実際に手元でやってみたが、自動で修正はされなかった。

```console
[root@localhost node-express]# npx eslint --fix .

/root/workspace/node-express/src/middleware/custome-openapi-validator.js
  3:1  error  Imports should be sorted alphabetically       sort-imports
  4:1  error  Expected 'all' syntax before 'single' syntax  sort-imports

✖ 2 problems (2 errors, 0 warnings)
```

そのため、もし自動でimportの順序を直したい場合には以下の章で取り上げる[eslint-plugin-import](https://github.com/import-js/eslint-plugin-import)を利用する事になる。

### [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import)を使ってimportを自動整形する
使い方は公式にある通りで、パッケージを追加し、recommendと言われているルールはひとまず継承するように設定する。

```console
yarn add --dev eslint-plugin-import
```
```json:.eslintrc.json
{
	...
	"extends": [
		"eslint:recommended",
		"plugin:import/recommended",
		...
	],
	...
}
```

ソースコード全体は以下。

https://github.com/yuta-katayama-23/node-express/commit/4fc3ed5b97f41947a6f024bb172123380d9448e3

ここで1点、ググると以下のようにextendsに設定してさらに`plugins`にまで`imports`を記載しているものを見かけるが、extendsしているならpluginsの設定は不要。理由は[ソースコード](https://github.com/import-js/eslint-plugin-import/blob/main/config/recommended.js)を見ればわかるように、`plugin:import/recommended`をextendsに記載すると`plugins: ['import'],`や`rules: {...}`、`parserOptions: {...}`が自身の.eslintrc.jsonにも継承されるため。

肝心の自動整形のためのルールは[order](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md)というものになるので、以下のように設定すると、`eslint --fix`でimportを自動整形してくれるようになる。

```json:.eslintrc.json
{
	...
	"extends": [
		"eslint:recommended",
		"plugin:import/recommended",
		...
	],
	"rules": {
		...
		"import/order": [
			"error",
			{
				"alphabetize": { "order": "asc" }
			}
		]
	},
	...
}
```
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/d02892c1-0a59-47f4-b8f5-aa5853f1e602.gif)

※注意として、`"sort-imports": "error"`が残っていると以下のようにルールが競合してしまいエラーが残り続けるので、eslint-plugin-importを利用する場合にはsort-importsはoffにする必要があるだろう。

```console
[root@localhost node-express]# npx eslint --fix .

/root/workspace/node-express/src/index.js
  6:1  error  Imports should be sorted alphabetically  sort-imports

/root/workspace/node-express/src/middleware/custome-openapi-validator.js
  3:1  error  Expected 'all' syntax before 'single' syntax  sort-imports

✖ 2 problems (2 errors, 0 warnings)
```

※今回、`.eslintrc.json`に`import/order`のルールを明示的に設定していたが、これはデフォルトのルールセット（[config](https://github.com/import-js/eslint-plugin-import/tree/main/config)にあるもの）にはなさそうなため、自分で明示的的に設定する必要があったため（extendsしても有効にならないという意味）。

- 参考：[[ESLint] eslint-plugin-importを利用して自動でimportをアルファベット順にソートする](https://miyahara.hikaru.dev/posts/20200501/)