ESLintとPrettierの設定をドキュメントを丹念に見ながらやる(2022年2月時点)
(2022/2/17 更にドキュメントを詳しく参照するように加筆と、一部コマンドを修正しました✍)
ESLintとPrettierの設定、皆さんどうされていますか?🤔
私は結構雰囲気でググった記事を参考にやっていました。
ですが、いろんなところで言及されているところですが、ESLintとPrettier周りは過去推奨だったものが現在非推奨になっていたりと、移り変わりがあります。
今では非推奨になっているプラグインを用いている過去記事などあり、それをあたっている方もいらっしゃるかもしれません。
各々その時々ドキュメントを参照するのがベストですが、今回は、2022年2月現在、最新のドキュメントを丹念に見ながらESLintとPrettierの設定をしてみます。
おまけとして、husky+lint-stagedとeslint-plugin-importの設定もしていきます。
ESLintの設定から
まず設定するのに、今回適当なViteのTypeScriptプロジェクトを用意しました。
コマンドでプロジェクトを作成していきましょう。
yarn create vite my-eslint-prettier-husky --template vanilla-ts
git initしてここでinitial commitしておきます。
こちらのドキュメントを参考にやっていきます。
yarn add eslint --dev
します。簡単に始めたかったら、対話式のyarn create @eslint/config
してねと書かれているので、そちらを試してみます。
聞かれた全文と私の回答は下記になります。
(訳)どのようにESLintを使うか?
? How would you like to use ESLint? …
To check syntax only
To check syntax and find problems
❯ To check syntax, find problems, and enforce code style
(訳)どのようなモジュールを使うか?
? What type of modules does your project use? …
❯ JavaScript modules (import/export)
CommonJS (require/exports)
None of these
(訳)使用しているフレームワークは?
? Which framework does your project use? …
React
Vue.js
❯ None of these
(訳)TypeScriptは使っているか?
? Does your project use TypeScript? No / › Yes
(訳)コードはどこで走らせるか?
? Where does your code run? … (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
Node
(訳)スタイルの設定はどのようにするか?
? How would you like to define a style for your project? …
❯ Use a popular style guide
Answer questions about your style
(訳)どのスタイルガイドにするか?
? Which style guide do you want to follow? …
Airbnb: https://github.com/airbnb/javascript
Standard: https://github.com/standard/standard
❯ Google: https://github.com/google/eslint-config-google
XO: https://github.com/xojs/eslint-config-xo
(訳)設定ファイルの拡張子は?
? What format do you want your config file to be in? …
❯ JavaScript
YAML
JSON
@typescript-eslint/eslint-plugin@latest eslint-config-google@latest @typescript-eslint/parser@latest
(訳)これらのパッケージを今npm installするか?
? Would you like to install them now with npm? › No / Yes
最後のは、yarnでインストールしたかったのでスキップしました。なので
yarn add @typescript-eslint/eslint-plugin@latest eslint-config-google@latest @typescript-eslint/parser@latest --dev
します。
出来上がった.eslintrc.js
が下記になります。
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"google"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
}
}
yarn eslint src/main.ts
でLintのチェックを走らせてみます。
/Users/ユーザー名/products/my-eslint-prettier-husky/src/main.ts
1:21 error Missing semicolon semi
3:60 error Missing semicolon semi
8:2 error Missing semicolon semi
✖ 3 problems (3 errors, 0 warnings)
3 errors and 0 warnings potentially fixable with the `--fix` option.
Googleのスタイルではセミコロンはありになっているようです。
ここでyarn eslint src/main.ts --fix
を走らせると警告のあった箇所が修正されファイルにセミコロンが追加されます。
私はセミコロンなしのプロジェクトにすることが多いので、セミコロンなし設定を追加します。
...
"rules": {
"semi": ["off", "always"],
}
...
Get Startedページにある通り、rulesは、下記のように設定できます。
"off"
or 0 - turn the rule off ルールをオフにする
"warn"
or 1 - turn the rule on as a warning (doesn't affect exit code) 警告を出す(コードは終了しない)
"error"
or 2 - turn the rule on as an error (exit code will be 1) エラーを出す(コードを1で終了する)
配列の二番目のオプション(上記で言えばalways
)や、どのようなルールがあるかは下記から参照していってください。
distを出しておきたいので、一旦ここでyarn build
します。
distをESLintからignoreしたいので、.eslintignore
ファイルを作り、下記を設定します。
dist/**/*.js
node_modulesは予めignoreされているようなので安心ですね。
In addition to any patterns in the .eslintignore file, ESLint always follows a couple of implicit ignore rules even if the --no-ignore flag is passed. The implicit rules are as follows:
- node_modules/ is ignored.
- dot-files (except for .eslintrc.*), as well as dot-folders and their contents, are ignored.
さて、この段階で思った。—fixでフォーマットできるならPrettierは不要なのではないか?(素人)
Prettier公式に答えがあります。
PrettierはFormatting rulesを助けてくれるが、Code-quality rulesについては何もしません、とあります。
In other words, use Prettier for formatting and linters for catching bugs!
言い換えれば、フォーマットにはPrettierを使用し、バグをキャッチするにはリンターを使用してください。とのことです。
上記ドキュメントで例として挙げられているもので言えば、
Formatting rules
・max-len コードの1行の文字数の制限
・no-mixed-spaces-and-tabs スペースとタブが混合していないか
・keyword-spacing if文などのスペースの調整
・comma-style カンマのスタイル
Code-quality rules
・no-unused-vars 未使用の変数の警告
・no-extra-bind 不要なbindの警告
・no-implicit-globals グローバルスコープでの宣言の警告
・prefer-promise-reject-errors Promiseのrejectにエラーオブジェクトオブジェクト必須の警告
と、内容を見てみると2つの性質の違いがわかってきました。
ここからPrettierを入れていきます。
Prettierの設定
下記参考にやっていきます。
yarn add --dev --exact prettier
echo {}> .prettierrc.json
touch .prettierignore
.prettierignoreにdistを記述
Prettierもnode_modulesは予めignoreされています。
Prettier CLI will ignore files located in node_modules directory. To opt out from this behavior, use --with-node-modules flag.
下記部分を読むと、eslint-config-prettier
をインストールして、ESLintとPrettierが互いにうまく機能するようにします、とあります。こちらを設定すると、Prettierと競合する可能性のあるESLintルールをオフにしてくれます。
こちらにLinterと併用する場合のドキュメントがあります。
eslint-config-prettierのドキュメントを見ながらやっていきます。
yarn add eslint-config-prettier --dev
します。
必ず他の設定を上書きするよう、"prettier"
を"extends"
の最後にしてねとありますのでそのようにします。
Then, add "prettier" to the "extends" array in your .eslintrc.* file. Make sure to put it last, so it gets the chance to override other configs.
{
"extends": [
"some-other-config-you-use",
"prettier"
]
}
yarn prettier --write .
してみます。
セミコロンがつく、ダブルクオーテーションになるという修正がなされたので、差分が出ないよう.prettierrc.json
に下記記述を入れます。
{
"semi": false,
"singleQuote": true
}
ここまででPrettierの設定はおしまいです。
ここからおまけでhuskyとeslint-plugin-importの設定をしていきます。
おまけ:huskyとeslint-plugin-importの設定
下記を見ながらhuskyの設定をします。
huskyとlint-stagedを組み合わせると、コミット時にコマンドを実行することが出来ます。
こちらでコミット時にESLintとPrettierを走らせていきます。
yarn add --dev husky lint-staged
npx husky install
npm set-script prepare "husky install" // これいま上手く行かないかも。エラー吐いたので私は手動でpackage.jsonのscripts”にprepare": "husky install”を追加しました。
npx husky add .husky/pre-commit "npx lint-staged"
.lintstagedrc.json
に拡張子ごとに走ってほしいコマンドを設定します。
{
"*.ts": "eslint --fix",
"*.{ts,json,md}": "prettier --write"
}
私はlint-stagedのコマンドがVSCodeのGUIのみyarnやnpxがnot foundのエラーになってしまうこともあったのですが、下記記事(古い記事ですが)のパスを通すのをホームディレクトリの.huskyrc
でおこなったところ解消されました。
huskyが動作しているかどうか見てみましょう(長い文とダブルクオーテーション)
import './style.css'
const app = document.querySelector<HTMLDivElement>('#app')!
const longLongMessage = "長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ"
app.innerHTML = `
<h1>Hello Vite!</h1>
<p>${longLongMessage}</p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`
↓コミットしたところ、フォーマットされました。
import './style.css'
const app = document.querySelector<HTMLDivElement>('#app')!
const longLongMessage =
'長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ長い長いメッセージだよ'
app.innerHTML = `
<h1>Hello Vite!</h1>
<p>${longLongMessage}</p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`
今度はeslint-plugin-import
の設定をしていきます。
いままで参加させていただいたプロジェクトで、importのorderをプラグインで並べ替えていたことがあったので再現してみたくなりました。
こちらのプラグインを使用することになります。
TypeScriptでは、@typescript-eslint/parser
とeslint-import-resolver-typescript
を準備してくれよなと書いてあるので入っていない場合はインストールしておきます。
デフォルトではルールはオフになっている模様なので、設定していきます。
All rules are off by default. However, you may configure them manually in your .eslintrc.(yml|json|js), or extend one of the canned configs:
...
plugins: ['@typescript-eslint', 'import'], // import追加
rules: {
semi: ['off', 'always'],
"import/order": [2, {"alphabetize": { "order": "asc" }}], // 追加
},
...
設定については下記にドキュメントがあります。
こちらで下記のように書いたimportが
import { testB } from './test-modules/test-b'
import { testA } from './test-modules/test-a'
下記のようにコミット時並べ替えられるようになりました。
import { testA } from './test-modules/test-a'
import { testB } from './test-modules/test-b'
これにて設定は一旦終了です!
特に見どころはないですが、ここまでの作業は下記リポジトリにあります。
最後に
最近は一次情報に当たる、ドキュメントを検索しまくって情報を掘り当てるというのにハマっていますが、この記事も普段ゴリゴリにESLintとPrettierを使っている人にとっては当たり前の記事だったかもしれません。
今回ほぼドキュメントの内容を掘っているだけですしね。
でも、ESLintとPrettierについて、ドキュメントベースの記事がもっとあってもいいのではないかと思っていたので、書いてみました。
何か不備ありましたらご指摘いただけると喜びます!
Discussion