ESLintによるJavaScriptコーディングルールの強制

前提

要素 バージョン 関連記事
node/npm 7.4.0/4.1.2 Debian8.7にMEAN開発環境を構築する
gulp 3.9.1 Babel+Gulpで始めるES6

概要

構文チェックツール”ESLint”を用いて、JavaScriptのコーディングルールを強制し、コード品質を高める。

また、gulpによってESLintの自動実行することで、リアルタイムにコードを検証する。

JavaScript構文チェックツールについて

JavaScript構文チェックツールとは、JavaScriptコード中に潜む、シンタックスエラーやバグの元となりえる構文を静的に解析して通知してくれるツールのこと。

例えば以下のJavaScriptコードは、JavaScriptの仕様上では正常に動作する。

var hoge = 3;
var fuga = function(a , b , a) {
console.log(a + b);
}
fuga(1 , 2 , 3)

しかし、上記コードは以下の問題を含んでいる

  • 変数hogeは使用されていない(1行目)
  • 関数fugaに使用されていない第三引数がある(2行目)
  • 関数fugaの第一引数と第三引数の名前が重複している(2行目)
  • インデントされるべき行でされていない(3行目)
  • セミコロンが挿入されていない(5行目)

このような、実行時のエラーとはならないが、潜在的なバグの原因となったり、可読性を損ねるようなコードが含まれている場合にそれを通知するのが構文チェックツールの役割だ。

ESLintについて

ESLintは、他の構文チェックツールと比べて以下の特徴を持っている

  • 全ての検証ルールについて、検証のON/OFFを選択できる
  • 独自の検証ルールを作成することができる
  • ルールごとのドキュメントが充実している

今回はNode環境上にESLintを導入し、推奨の設定に加えていくつかの検証ルールを追加でONにすることにする。

ESLintのインストール

本記事では、gulp上でESLintを利用するので、gulp-eslintをnpmでインストールすることで、依存先のeslintもまとめてインストールする。

npm install -D gulp-eslint

.eslintrc.jsonの作成

eslintの設定は、隠しファイルである.eslintrc.jsonに記述する。今回作成したeslintrcを以下に示す。

{
    "extends": ["eslint:recommended"],
    "plugins": [],
    "parserOptions": {},
    "env": {
      "browser": true,
      "es6": true
    },
    "globals": {},
    "rules": {
      "no-var": "error",
      "semi": "error",
      "block-spacing": "error",
      "indent": ["error" , 2],
      "no-mixed-spaces-and-tabs": "error",
      "no-multiple-empty-lines": ["error" , {"max": 1}],
      "no-trailing-spaces": "error",
      "space-infix-ops": "error",
      "dot-notation": "error",
      "eqeqeq": "error",
      "no-else-return": "error",
      "no-loop-func": "error",
      "arrow-parens": "error",
      "arrow-spacing": "error",
      "no-console": "warn",
      "no-undef": "off"
    }
}

eslintrcの主な構成は以下の通り

  • extendsでベースとなる設定を指定し、ここではeslintの推奨設定を継承する(2行目)
  • eslintの対象コードの実行環境を指定し、ここではブラウザ上で動作し、ES6を利用していることを記述する(5行目)
  • 追加ルールを指定する。ベースとなる推奨設定に含まれるルールを記述する必要はない(10行目)

ruleは{ルール名: 設定}の形式で記述する。基本的に設定は、以下の3択で指定し、場合によっては追加設定情報を配列で与える。

  • “error”: ルールに反している場合に警告を出力する(強調)
  • “warn”: ルールに反している場合に警告を出力する(控えめ)
  • “off”: 警告を出力しない

上記eslintrcに含まれるルールは以下の通り

ルール名 ルール内容 異常系 正常系
no-var varの使用を禁止 var hoge let hoge
semi セミコロンの省略を禁止 let hoge let hoge;
block-spacing 単一行ブロックで内側スペースの挿入を強制 if(hoge) {fuga();} if(hoge) { fuga(); }
indent(2) インデントをスペース2字の強制
no-mixed-spaces-and-tabs タブとスペースのインデントの混在を禁止
no-multiple-empty-lines(1) 2行以上連続した空行を禁止
no-trailing-spaces 行の末尾へのスペースの付与を禁止
space-infix-ops 演算子の前後にスペースを強制 a=b+c; a = b + c;
dot-notation ドット表記可能な場合にドット表記を強制 hoge[‘fuga’] hoge.fuga
eqeqeq ==の使用を禁止 a == b a === b
no-else-return else文での不要なreturnを禁止
no-loop-func ループ内で関数を定義することを禁止
arrow-parens アロー関数の特定フォーマットを強制 (a) => a * 2; a => a * 2
arrow-spacing アロー関数の矢印の前後にスペースを強制 a=>a * 2; a => a * 2
no-console console.logの禁止
no-undef 宣言されていない変数の使用を禁止

※ no-consoleはデバッグでは使用したいため、errorではなくwarningに設定
※ no-undefは、外部ライブラリで宣言された変数を利用することがあるのでoffに設定

gulpfileを編集

var gulp = require('gulp'),
    eslint = require('gulp-eslint');

gulp.task('eslint' , function() {
  return gulp.src('app/scripts/*.js')
    .pipe(eslint())
    .pipe(eslint.format())
});

gulp.task('watch' , function() {
  gulp.watch('app/scripts/*.js' , ['eslint']);
});

gulp.task('default' , ['babel' , 'eslint' , 'watch']);

上記gulpfileにて、gulp実行時及びapp/scripts/*.jsに変更が生じた場合に、eslintを実行し、errorかwarningが発生した場合に警告を出力する。

デモ

画面左側でJavaScriptのコーディングを行い、画面右側でESLintを実行するgulpが動いている。
デモ内では、初めに「varの使用を禁止」「セミコロンの使用を強制」「参照されない変数の宣言禁止」に引っかかるコードを記述し、ESLintに指摘を受けながらそれを修正している


(クリックで拡大)

所感

  • 自分の中でコーディングルールを定めでも、それを実行できてないことも少なくない。ESLintを導入すると大リーグボール養成ギブスを付けているかのような感覚でコーディングすることになり、初めは息苦しくも感じるが、それが自然とできるようになってくると、コーディングスタイルの一貫性が取れるようになり良いコードを無意識で書けるようになると思う。
  • 例によってgulpとの相性は最高に良い。デモのように画面を分割してリアルタイムで検証できるのは、まるで統合開発環境を使ってるようで気持ちが良い
  • 今回始めてgifアニメーションを撮ってみたが、結果的にテイク10ぐらいかかった。何故録画してるとタイポが増えるのだろうか。撮影は大変だが、百聞は一見に如かずなので今後も無駄にテキスト増やすよりもデモを用意するようにしよう

参考

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です