vue-element-adminにPrettierを導入して、ESLintと競合しないようにするメモです。
環境
- MacOS Big Sur
- Node.js 14.15.1
- npm 6.14.8
やりたいこと
- 保存時にPrettierで整形できるようにする
- PrettierとESLintの整形が競合しないようにする
方針
現在推奨されているのは、eslint-config-prettierでESLintのフォーマットに関するルールをオフにして、ESLintとPrettierを個別に実行する方法のようなので、その方針でやります。
参考: Prettier と ESLint の組み合わせの公式推奨が変わり plugin が不要になった
手順
- Prettierの導入
- Prettierの設定をESLintに寄せる
- Prettierとの競合をチェックして、ESLintのフォーマットルールをオフにする
1. Prettierの導入
npm install --save-dev prettier
インストールしたら、VSCodeのPrettierの拡張機能をインストールして、setting.jsonに以下を追記します。
{
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[css]":{
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
}
これでファイル保存時にPrettierでフォーマット出来るようになると思います。
2. Prettierの設定をvue-element-adminのESLintの設定に寄せる
既に存在するファイルに合わせるために、ひとまずPrettierの設定をvue-element-adminのESLintの設定に寄せることにします。
まず、プロジェクトルートに.prettierrc.jsを作成して、以下を追記します。
module.exports = {
singleQuote: true,
semi: false,
arrowParens: 'always',
trailingComma: 'none',
printWidth: 100
}
上の4つの設定はvue-element-adminのESLintに寄せるための設定です。printWidthに関しては、デフォルトでは80なのですが、80だと(特にVueのテンプレートが)縦に長くなって読みづらかったので100にしました。
この設定を
- src/store/modules/user.js
- src/views/login/index.vue
の2つで試してみると、JSファイルに関しては問題がなかったのですが、VueファイルはESLintの整形結果とPrettierの整形結果が異なっているところがありました。
例えば、
<!-- prettier後 -->
<el-button
:loading="loading"
type="primary"
style="width: 100%; margin-bottom: 30px"
@click.native.prevent="handleLogin"
>Login</el-button
>
<!-- ESLint後 -->
<el-button
:loading="loading"
type="primary"
style="width: 100%; margin-bottom: 30px"
@click.native.prevent="handleLogin"
>Login</el-button>
のようなところがありました。これはprettierが長い行を折り返したときに変になっていて、以下のようにすると解決します。
<!-- こうするとPrettierとESLintの整形結果が一致する -->
<el-button
:loading="loading"
type="primary"
style="width: 100%; margin-bottom: 30px"
@click.native.prevent="handleLogin"
>
Login
</el-button>
他の競合箇所は次の章で直すことにします。
3. Prettierとの競合をチェックして、ESLintのフォーマットルールをオフにする
ESLintにはフォーマットをさせない方針なので、ESLintからフォーマットに関するルールを削除します。eslint-config-prettierをextendすればフォーマットのルールをオフに出来るのですが、eslintrcのextendsよりrulesが優先されるようなので、結局rulesを消す必要があります。
まずはeslint-config-prettierを導入します。eslint-config-prettier
npm install --save-dev eslint-config-prettier
module.exports = {
extends: ['plugin:vue/recommended', 'eslint:recommended', 'prettier'], // prettierを追記
}
次にPrettierとの競合をチェックして、フォーマットに関するルールを消します。以下のコマンドでPrettierとの競合をチェックすることが出来ます(eslint >= 7.0が必要なようなのでアップデートします)。
npx eslint-config-prettier src/views/login/index.vue
❯ npx eslint-config-prettier src/views/login/index.vue
npx: installed 1 in 1.424s
The following rules are unnecessary or might conflict with Prettier:
- array-bracket-spacing
- arrow-spacing
- block-spacing
- brace-style
- comma-dangle
- comma-spacing
- comma-style
- dot-location
- eol-last
- generator-star-spacing
- indent
- jsx-quotes
- key-spacing
- keyword-spacing
- new-parens
- no-extra-parens
- no-extra-semi
- no-floating-decimal
- no-mixed-spaces-and-tabs
- no-multi-spaces
- no-multiple-empty-lines
- no-spaced-func
- no-trailing-spaces
- no-whitespace-before-property
- object-curly-spacing
- operator-linebreak
- padded-blocks
- semi
- semi-spacing
- space-before-blocks
- space-before-function-paren
- space-in-parens
- space-infix-ops
- space-unary-ops
- template-curly-spacing
- vue/html-closing-bracket-newline
- vue/html-closing-bracket-spacing
- vue/html-end-tags
- vue/html-indent
- vue/html-quotes
- vue/max-attributes-per-line
- vue/mustache-interpolation-spacing
- vue/no-multi-spaces
- vue/no-spaces-around-equal-signs-in-attribute
- wrap-iife
- yield-star-spacing
The following rules are enabled with config that might conflict with Prettier. See:
https://github.com/prettier/eslint-config-prettier#special-rules
- curly
- vue/html-self-closing
The following rules are enabled but cannot be automatically checked. See:
https://github.com/prettier/eslint-config-prettier#special-rules
- no-unexpected-multiline
- quotes
1番上のグループは不要そうなので、該当するルールがeslintrcにあれば消します。vueに関するルールは残しておきました(max-attributes-per-lineを消すと縦に長くなってしまったため)。
該当するルールを消してもう一度チェックすると以下のようになりました。
❯ npx eslint-config-prettier src/views/login/index.vue
The following rules are unnecessary or might conflict with Prettier:
- vue/html-closing-bracket-newline
- vue/html-closing-bracket-spacing
- vue/html-end-tags
- vue/html-indent
- vue/html-quotes
- vue/max-attributes-per-line
- vue/mustache-interpolation-spacing
- vue/no-multi-spaces
- vue/no-spaces-around-equal-signs-in-attribute
The following rules are enabled with config that might conflict with Prettier. See:
https://github.com/prettier/eslint-config-prettier#special-rules
- curly
- vue/html-self-closing
The following rules are enabled but cannot be automatically checked. See:
https://github.com/prettier/eslint-config-prettier#special-rules
- no-unexpected-multiline
- quotes
とりあえずこれで良しとします。
あとはbrタグが競合していたので、rulesに以下を追記して直しました。参考
module.exports = {
rules: {
"vue/html-self-closing": [2, {
"html": {
"void": 'always',
}
}],
}
これでprettierとESLintの競合が(ほぼ)起きなくなりました。あとはコミット前にprettierを実行するようにpackage.jsonに追記します。
{
"lint-staged": {
"src/**/*.{js,vue}": [
"prettier --write", // 追記
"eslint --fix",
"git add"
]
}
}
以上です。ESLintからフォーマットに関するルールを完全に消そうと思うと、extendsしているルールを見る必要がありそうですが、とりあえずこれで良しとします。
Vue.jsスタイルガイドとeslint-plugin-vue検証ルールのマッピング
ESLintのRulesのドキュメント
感想
Prettierはガチガチに整形してくれるイメージがありましたが、整形結果が一意では無いことを知りました。Prettierを使うとVueのスタイルガイドに添えないところが少し出てくるのかなぁと思いました。