先日、JSCS を JSX 対応というか ES6 対応版に入れ替えたのだけど、JSHint は JSX 対応に入れ替えられていなかった。
JSHint には「esnext」というルールがあるので、これを true にしてやれば JSX 構文にも対応するのかと思いきや、どうもそういう動きはしていないみたい。
「時代はESLint。JSLintでもJSHintでもなくESLint。」みたいな記事をみると、ESLint に鞍替えしたほうがいいのかなぁとも思いつつ、既存ルールをそのままお引っ越しする方法が分かっておらず、ひとつひとつ載せ替えるのにも時間がかかってしまうなぁという思いでちょっと停止してしまっていた。
いまのプロジェクトの状況だと、この「既存ルールの載せ替えにかけるコスト」を「別のタスクを消化するコスト」に割り当てるのが正しいと思っていての判断。終わっているはずのものが終わっていなかったりしているのだよ。あわわわわ。
とは言いつつも「構文チェックを通していないコードをリポジトリに登録していく状態」についてずっと気になっていた。コードレビュー時に指摘すれば回避できる話ではあるけど、こういうツールで指摘される程度のミスをいちいち人間が指摘するのも時間の無駄になる。
クロコスに入ったころには、まだ構文チェックツールまわりが整備されていなかったので、オレ自身がだいぶそういう情けない指摘を受けてきた。これは本当にレビューする側・レビューされる側の双方にとって時間の無駄だし、特にレビューする側のやる気をなくしてしまう。だからチームを健全に運営していく上でも、こういったチェックツールを導入するのが正しいと思っている。
そういうバックグラウンドがあるので、今日、ちょっと手の空いた時間(と言っても20時過ぎだったけど)に調査を開始したら、grunt-contrib-jshint-jsx というパッケージを見つけた。これは grunt-contrib-jshint を fork して、JSX 対応をしたプロジェクトの様子。
いまのプロジェクトでは grunt-contrib-jshint を使っているので、これを差し替えて対応できるなら「既存ルールの載せ替えにかけるコスト」はかけずに済むんじゃないかと思って対応してみた。
Gruntfile.js では、 *.js
と *.jsx
とに分けてルールを適用したかったので次のような形で書いてみた。
grunt.initConfig({
'jshint-jsx': {
js: {
options: {
jshintrc: '.jshintrc',
force: true
},
files: {
src: ['src/**/*.js']
}
},
jsx: {
oprions: {
jshintrc: '.jshintjsxrc',
convertJSX: true,
force: true
},
files: {
src: ['src/**/*.jsx']
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint-jsx');
grunt.registerTask('default', ['jshint-jsx']);
*.js
用のルールは、これまでどおり .jshintrc
に書いて、*.jsx
用のルールは新たに .jshintjsxrc
に記述するようにした。.jshintjsxrc
はオレが勝手に付けた名前のファイルなので、JSHint とか grunt-contrib-jshint-jsx 用のファイル名というわけではない。
grunt-contrib-jshint-jsx 独自のルールとしては convertJSX: true
がある。これを true
にしておくと「JSHint を実行する前に JSX を JS にコンバートする」という動きをしてくれる様子。jsx という拡張子が付いたファイルはデフォルトで true
になるって書いてあるけど、意図的に明示している。
これを実行するには grunt コマンドを叩くわけだけど、上記の場合は default のタスクに jshint-jsx を組み込んであるので、grunt を叩くだけで jshint-jsx タスクが実行される。
% grunt
また、個別に実行したい場合には次のようにしてやれば良い(この辺は Grunt の話だけど)。
*.js
ファイルだけ対象にしたいとき% grunt jshint-jsx:js
*.jsx
ファイルだけ対象にしたいとき% grunt jshint-jsx:jsx
*.js
も *.jsx
も対象にしたいとき% grunt jshint-jsx
この jshint-jsx:js
の最後の「js」の部分は、先ほどの Gruntfile.js でのプロパティ名を「js」にしているからそうなっているだけで、 grunt-contrib-jshint-jsx の機能とかではないことに注意かな。この部分で定義しているプロパティ名が「js」だから「jshint-jsx:js」になっているだけ。
'jshint-jsx': {
js: {
jshint-jsx:jsx
の jsx
の部分も同様。こういう名称はミスリードを生みやすいので、説明のときには避けたほうが無難だね。ここでは使っちゃったけど。
ちょっとまだルールに関しては調整が必要かなとも思っているけど、これでチェックする土台はできたので、このあとプロジェクトの進行と共にルールを育てていけば良さそうだ。