マナリンクのソースコード整形(Prettier, ESLint, StyleLint)設定-2021年5月版
弊社のオンライン家庭教師サービス「マナリンク」で設定しているソースコード整形周りの設定を公開していきます。
以前マナリンクのフロントエンド開発環境【基礎編/TypeScript,ESLint,Jest,Sentry】 にて、「以前は僕もPrettierを愛用していましたが、最近のプロジェクトではESLintだけで事足りることも多く、存在意義がよくわからなくなってきています。このへんは分かったら記事化します。」と書きました。そのあと結局PrettierとESLintを併用する形にしたので、設定や目的などをまとめてみます。
husky, lint-stagedの設定
まずは、package.jsonにおけるhuskyとlint-stagedの設定を示します。
"lint-staged": {
"*.vue": [
"prettier --write",
"eslint --fix",
"stylelint --fix"
],
"*.{js,ts}": [
"prettier --write",
"eslint --fix"
],
"*.{css,scss}": [
"prettier --write",
"stylelint --fix"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
prettier-eslintやprettier-stylelintは使わず、愚直に連続でコマンド実行する形にしています。
Nuxtプロジェクトのため、基本的なファイルはVue、JS、TS、CSS、SCSSです。
※huskyは現在はv4を使っていますが、v6にアップデートする差分をPull Requestするところまでは進めています。husky v6はいくつか設定が変わっていますが、migration toolが提供されているのでこれを実行すると割とスムーズです。
prettier-eslintやprettier-stylelintを使わない理由
以下のPrettier公式ドキュメントのNotesをご覧ください。
雑に和訳すると実行速度が遅くなるからと書かれています。よほど差分が大きくない限り、prettier-eslintを使ってもprettierを直接実行してもほとんど速度が変わらないな、と体感的には思うのですが、公式が言うので従ったほうがいいかなと思っています。
それに、依存する(package.jsonに載る)ライブラリはできる限り少ないほうが良いと思います。使わなくても同等以上の速度で動作するのであれば、使わなくていいのかなと思います。
prettierの設定
続いてprettierrc.jsを貼ります。こちらのファイルを参照してPrettierが実行されます。
module.exports = {
printWidth: 120,
semi: false,
singleQuote: true,
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: 'avoid',
}
semi: false
現状マナリンクでは、セミコロンはfalseに設定しています。しかし以下のAirbnbやGoogle Style Guideを読む限りは特定のケースで行末にセミコロンがあるとみなす(ASI)ことに起因するバグを防ぐために、予めセミコロンを付けておくことを推奨しています。
it uses a set of rules called Automatic Semicolon Insertion to determine whether or not it should regard that line break as the end of a statement
ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break.
Every statement must be terminated with a semicolon. Relying on automatic semicolon insertion is forbidden.
そのため、Next.jsで開発しているマナリンクTeachersやFirebaseリポジトリではすでにセミコロンを付けるようにしています。
ちなみにNext.jsそのもののリポジトリを見ると普通にsemi: false
だったりするので、実際問題は実害としてASIがバグを誘発することは少ないのかもしれません。
bracketSpacing: true
BracketSpacingは個人的な見やすさでtrueにしましたが、よくネット上で見るコードは空白が空いていないことも多いので、ここも好みかもしれません。
ESLintの設定
module.exports = {
extends: [
'@nuxtjs/eslint-config-typescript',
'plugin:import/typescript',
'plugin:vuejs-accessibility/recommended',
'plugin:vue/recommended',
'prettier',
],
plugins: ['vuejs-accessibility'],
rules: {
// 中略
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
// Vue3対策
'vue/no-deprecated-slot-attribute': 2,
'vue/no-deprecated-scope-attribute': 2,
'vue/no-deprecated-slot-scope-attribute': 2,
'vue/no-deprecated-filter': 2,
'vue/no-deprecated-v-bind-sync': 2,
'vue/no-deprecated-v-on-number-modifiers': 2,
'vue/no-deprecated-events-api': 2,
'vue/no-deprecated-functional-template': 2,
'vue/no-deprecated-html-element-is': 2,
'vue/no-deprecated-vue-config-keycodes': 2,
'vue/no-deprecated-dollar-listeners-api': 2,
'vue/no-deprecated-v-on-native-modifier': 2,
'vue/no-deprecated-dollar-scopedslots-api': 2,
},
}
vuejs-accessibility
がすぐれものです。ありがちなものですとaltが指定されていないimgタグは避けようとか、divなどにonClickを当てるなら@keyupなども紐付けるようにしてね、とかがあり、詳しくなくてもa11yを適用できるようになってます。
あとはtemplate内部にコンポーネントがあったらケバブケースに統一するとか、Vue3で廃止予定の機能は使わないようにするとかです。
stylelintの設定
stylelintはstylelint-config-standard
を使いつつ、そのままだと利用が厳しいルールをOFFにしています。けっこう厳し目のルールが多い印象で、既存のソースコードがかなり怒られてしまいます。
{
"extends": "stylelint-config-standard",
"rules": {
"at-rule-no-unknown": null,
"selector-pseudo-element-no-unknown": null
}
}
prettierとLinterはどちらが先に実行されるべきか?
prettierとlinterを分けて実行するとなると、どちらを先に実行するのが良いか、という命題が生まれます。
私は現在prettierを先に、linterを後に実行しています。理論的には、eslint-config-prettier
を入れているためどちらが先でも問題がないはず・・・です。
しかしこの記事のように、prettierを最後に実行するように指定する意見も見受けられます(悲しいことに、この記事ではなぜその順番が望ましいのかの回答が得られませんでした)。
逆にこの記事では、npm scriptsのfixとしてprettierを実行してからeslintしています。
prettierを実行した結果としてlint違反になるコードが生まれることはないでしょうが、lintを実行した結果としてprettier違反になるコードが生成されることは全く無くはない気がしています。
ということは、lintを先に実行したほうがより良いといえるのでしょうか。
何かしら明確な答えが得られましたら追記しようと思います。
Prettierを使う意味
ESLintのルールを見ても、いくつかソースコードの見た目を良くするためのルールが見受けられます。たとえば行末の余分なスペースを検知するなどです。しかしPrettierを使うのはなぜなのでしょうか。
それについて当時の私自身に説明するとしたら以下のように話します:
Prettierはソースコードの見た目を良くして可読性を上げるために実行する。Linterはソースコードの機能面は変えずに、様々な観点でより望ましい実装方法を提示したり、Fixしてくれる。Linterの機能の中にPrettierが果たせる機能が含まれることもあるが、
eslint-config-prettier
(source)などを使うことで、競合するルールに関するLintをOFFにして共存する。それではESLintだけでPrettierの機能を完全に代替できるのでは?という疑問が出てくるのは自然であるが、Lintのルールには純粋に整形しか目的としないような、たとえば関数にある程度の個数の引数があれば改行してきれいに見せてくれるような整形は含まれない。したがってPrettierに整形を任せるほうがいい
以上です。
オンライン家庭教師マナリンクを運営するスタートアップNoSchoolのテックブログです。 manalink.jp/ 創業以来年次200%前後で売上成長しつつ、技術面・組織面での課題に日々向き合っています。 カジュアル面談はこちら! forms.gle/fGAk3vDqKv4Dg2MN7
Discussion