昔話
昔々、あるところに、構文チェックを一切しない、コードレビュー一切なし、動けばOK!の感覚で開発を行っていた、JavaScriptを使ったフロントエンド開発のプロジェクトがありました。
タブとスペースの混在で、インデントはめちゃくちゃ。
改行コードは、LFとCRLF混在。
変数宣言は、varとletとconstが混在。
文字列定義も、シングルクォーテーションとダブルクォーテーションが混在。
プロジェクトメンバーはなんと、ただインストールしただけのサクラエディタで開発を行っていたのです。
※ 決してサクラエディタをバカにしているわけではありません。
ちゃんと設定すればそれなりに使えるテキストエディタです。
だれがどう見てもクソコード量産プロジェクトである。
早くなんとかしなければ…
しかし、メンバー皆がバックエンドエンジニア。誰もフロントエンドのことなんて分からない。
誰もこれをどうにかできる知識を持っていなかったのである…
「.eslintrc.jsonってなんであるんですか??」
下っ端の開発メンバーの一人が、プロジェクト内にあるファイルに目をつけた。
中身は、
{
"extends": "airbnb"
}
これだけだった。
後に失踪する開発リーダーは言った。**「知らない。最初からあった。」**と。
下っ端はファイル名でググってみた
ESLintという単語が出てきた。
下っ端は、とある文章に目が止まった。
人によって異なるJavaScriptの書き方もチーム開発では揃っていないと気持ちが悪いし、バグのもとに…。構文チェックツール「ESLint」を導入すれば、スタイルガイドに合わせたチーム開発が捗るそうですよ。
あれ?これがあればこのクソコード量産プロジェクトがマシになるのでは?
下っ端は昼休みを使って、ひっそりと導入を試みることにした。
導入手順
環境
- OS:Windows 10
- エディタ:Visual Studio Code
ESLintインストール
npmを利用してインストールします。
ちなみにWindowsのNode.jsのインストールはこちら。
こだわりがなければ、Nextボタンをポチポチして待っていれば完了です。
自分のNode.jsのバージョンが古かったので、アップデートしておきます。
$ npm install -g npm
そしてnpmを利用して、ESLintをインストールします。
グローバル(非推奨)でいいならば、
$ npm install -g eslint
プロジェクトのみに適用したいならば、プロジェクト直下に移動して、
$ npm install -save-dev eslint
それなりに時間がかかるので、気長にインストール完了するのを待ちます。
VSCodeでの設定
VSCode側の設定をします。
VSCode本体のインストールはこちら。
拡張機能でESLintをインストールして再起動します。
ESLintで一番先頭に出てくるやつをインストールします。
eslint-config-airbnbをインストール
Cannot find module 'eslint-config-airbnb' Referenced from [.eslintrc.jsonまでのパス]
eslint-config-airbnbがないと怒られたので、eslint-config-airbnbをインストールします。
これは、「AirbnbのJavaScriptスタイルガイド」のことを指しています。
他にも、GoogleのJavaScriptスタイルガイドがあるらしいです。
ESLintをAtomに導入し、Reactの構文にも対応したAirbnbのJSスタイルガイドを使うを参考にさせていただきました。
今回のプロジェクトはES6 + Reactのプロジェクトだったので、下記のコマンドを実行します。
$ npm install --save-dev eslint-config-airbnb eslint-plugin-import eslint-plugin-react eslint-plugin-jsx-a11y eslint
エラーなく終了することを確認したので、VSCodeを再起動します。
そして、恐ろしいことが起こりました。
エラー件数が50000件以上出た
VSCodeを再起動して、適当なjsxを開いてみました。
そしたら下記のようなエラーがズラーッと出ました。
何が恐ろしいって、200行くらいしかないコードなのに、エラーが153件も出てることなんですよね。
プロジェクト全体だと、なんと50000件以上出ていました。
そして、さらなる問題点が…
発覚したのが開発終盤
ESLintを導入したのは自分だけ。この状況を知っているのが自分だけ。
開発リーダーは蒸発し、他メンバーは数人。
テストが始まる前にやることは唯一つ。
できる限りエラーを解決する
たとえば、Missing semiclon
は行末にセミコロンがないから出ているエラーです。
省略されているセミコロンを片っ端から追記しました。
String must use singlequote.
は、文字列の指定がシングルクォーテーションではなく、ダブルクォーテーションが使われているから出力されているエラーです。
すべてシングルクォーテーションに修正しました。
あとはswitch~case文に{}をつけるとか、自分でも簡単に修正できるものを片っ端から対応しました。
でもそれだけでは、さっぱり足りませんでした。
ruleの設定レベルを下げる
対応しきれないエラーに関しては、ruleを無効にしていきます。
ESLintでReact.js / ES6+ のコードをチェックする手順の説明がわかりやすかったです。
数値 | 意味 |
---|---|
0 | 無効 |
1 | 警告 |
2 | エラー |
そして、片っ端から0にしていきます。
// 0:無効, 1:有効(警告), 2:有効(エラー)
// デフォルトは2
"rules": {
// 無効にしているエラールール
"no-plusplus": 0, // 単項演算子は使用しないこと
"dot-notation": 0, // オブジェクトプロパティに対して.(ドット)でアクセスすること
"comma-dangle": 0, // オブジェクトまたは配列の最後の要素に対してカンマをつけないこと
"max-len": 0, // 1行80文字を超えないこと
"no-multi-spaces": 0, // インデント以外で複数スペースを使用しないこと
"react/forbid-prop-types": 0, // propTypesでobject型を使用しないこと
"prefer-template": 0, // 文字列結合はテンプレートリテラルを使用すること
"object-shorthand": 0, // オブジェクト定義時に短縮記法(ショートハンド)を使用すること
"no-return-assign": 0, // return宣言時に変数代入を行わないこと
"no-mixed-operators": 0, // 複数の演算子をカッコをつかわないで使用しないこと
"no-shadow": 0, // スコープ内の変数とスコープ外の変数を重複して使用しないこと
"react/prop-types": 0, // propsのvalidationを設定すること
"react/no-did-mount-set-state": 0, // componentDidMount()内でsetStateを使用しないこと
"jsx-a11y/label-has-for": 0, // labelタグに対してhtmlForを設定すること
"react/jsx-max-props-per-line": 0, // jsxの1行に指定できるprops数を1に設定すること
"react/jsx-first-prop-new-line": 0, // propertyは新しい行の最初に記載すること
"consistent-return": 0, // returnする型は常に一致させること
"no-restricted-syntax": 0, // 制限構文(for-ofなど)を使用しないこと
"react/no-array-index-key": 0, // キー項目にindexを使用しないこと
"yoda": 0, // ヨーダ記法で記載すること
"react/jsx-wrap-multilines": 0, // 複数行の結果を返すときに()で囲むこと
"jsx-a11y/href-no-hash": 0, // aタグでhref="//"と記載しないこと
"import/extensions": 0, // 自動的にimportされるjs拡張子などをimportに記述しないこと
"padded-blocks": 0, // ブロックスコープの最初と最後に空行を入れること
"no-lonely-if": 0, // elseブロック内に単独のif文を記述しないこと
"no-use-before-define": 0, // 変数や関数を使用する前に宣言すること
"react/prefer-stateless-function": 0, // Componentsをステートレスにするために純粋な関数を使用すること
"class-methods-use-this": 0, // thisを参照していないインスタンスメソッドは静的なメソッドにすること
"newline-per-chained-call": 0, // 1行の中に連続したメソッド、チェーンを記載しないこと
// 以下警告レベルに下げているエラールール
"eqeqeq": 1, // 型を含めた比較演算子を使用すること
"no-unused-vars": 1, // 未使用な変数や関数は削除すること
"no-param-reassign": 1, // 関数の引数に対して再代入しないこと
"prefer-const": 1 // 再代入しない変数はconstを使用すること
}
グローバル変数を許容する
許容するグローバル変数を定義していきます。
"globals": {
"window": true, // windowオブジェクトを許容する
"document": true, // documentオブジェクトを許容する
"location": true, // locationオブジェクトを許容する
"API": true, // APIオブジェクトを許容する
}
そしてクソコード量産プロジェクトは完遂された
下っ端がやけくそでソースコードを修正したことがバレることなく、テスト工程に入りました。
こういう自由度の高さは、炎上プロジェクトならではだと思います。(皮肉です。)
二度とゴメンな糞プロジェクトでした。
風のうわさだと、いまだにこのプロジェクト動いているらしいです。ばっかじゃねーの。
あとがき
本当であれば、開発始まってすぐに導入して、ルールを設定すべきだと思います。
愚直にESLintを導入した話の運用が参考になるかと思います。
ruleに関してわかりやすく表でまとまっているサイトがあったのですが、1年以上前の出来事なので、見つけられませんでした。
rule1つ1つのコメントもそこから、引用させていただきました。
見つかったら追記します。
※ 2018年9月4日追記
見つけました。ESLintのルール一覧は
ESLint ルール 一覧 (日本語)
がわかりやすいです。
当時はこれを見ながらルール無効にするもの、対応するものを選別していました。
ESLintの自動FIX機能
コメントにて教えていただきました。
ESLintのfix機能を使用することで、行末にセミコロンがないなどのエラーを自動的に修正してくれます。
コマンドは下記の通りです。
$ ./node_modules/eslint/bin/eslint.js [修正したいファイルパス] --fix
もしくはpackage.jsonに、
"scripts": {
"eslint": "eslint . --fix"
}
を追記して、下記のコマンドでも実行することができます。
$ npm run eslint
でも実行可能です。
参考文献
入門!JavaScriptの構文チェックが捗るESLintの設定と使い方 - WPJ
愚直にESLintを導入した話
ESLintでReact.js / ES6+ のコードをチェックする手順
ESLint ルール 一覧 (日本語)