yoshida

ESLintでJavaScriptの構文チェックを始める

今回はJavaScriptの構文チェックツールについてまとめました。
これからチェックを始める方が、基本的なチェックを始めるまでの方法を紹介したいと思います。

主な構文チェックツール(JSLint,JSHint,ESLint,JSCS)の特徴

記事作成時(2016年6月)、JavaScriptの構文をチェックできる主なツールには下記のようなものがあります。

JSLint
JSHint
ESLint
JSCS

どのツールを選択しても、何も使用しないよりは品質が大きく向上すると思いますが、
それぞれ出来ることや特徴が異なりますので、各ツールの特徴を把握した上で自分に適したツールを使用すると良いと思います。
この記事では、現時点で比較的注目度が高いESLintを使用します。

主な構文チェックツールの特徴は次の通りです。

JSLint

jslint

JS用Linterの元祖的存在。
作者は『JavaScript: The Good Parts』の著者です。
チェックルールは予め決められており、作者の考え方に従って厳しいチェックが行われますが、
作者個人の考え方に依存していることを欠点とする意見もあります。

JSHint

jshint

JSLintの欠点を補うために、JSLintからフォークされて作成されたツールです。
JSLintより柔軟で、設定ファイルを使用して、チェック項目のON/OFFを切り替えたり、チェック対象外のファイルを設定することもできます。
こちらのチェックで十分な場合も多いかもしれませんが、チェック項目の拡張ができなかったり、
発生したエラーの原因となるルールを特定しにくいなど、不便を感じる場合があるかもしれません。

ESLint

eslint

ESLint の考え方は「Everything is pluggable」。
全てのチェック項目は自由にON/OFFの切り替えが可能で、独自のルールを作成して追加することも可能です。
また既存のルールについては比較的ドキュメントが充実しています。
eslint/docs/rules at master · eslint/eslint

JSCS

jscs

構文チェックも可能ですが、エラーが発生した箇所をフォーマットに合わせて自動修正させることが可能です。
2016年4月、JSCSはESLintに統合されることが発表されました。

すぐできるESLintの使用環境

ESLint はカスタマイズの自由度がとても高い構文チェックツールですが、
複雑なカスタマイズをしようとすると、それなりに手間がかかります。

使ったことが無い方は、とりあえず手間を掛けずに一度ツールを使ってチェックしてみたい、
と思われるかもしれません。

公式サイトでは下記のページのようにソースを張り付けてチェックするページもあるのですが、
今後継続してツールを使用するためにローカルで使用するための環境を整えます。

ESLint Demo - ESLint - Pluggable JavaScript linter

1. Node.jsとnpmをインストール

ESLint の使用にはNode.jsとnpmが必要です。
インストール方法は省略しますが、下記のコマンドでそれぞれバージョンが表示されていればOKです。

node -v
npm -v

2. ESLintのインストール

npmを使用してESLintをインストールします。

npm install -g eslint

下記のコマンドでESLintのバージョンが表示されていれば、
ESLintのインストールは完了しています。

eslint -v

3. チェックするJSファイルを用意

ESLintがインストールされましたので、チェックしたいJSファイルを用意します。
今回は次のような内容のJSファイルを用意しました。

var list= [1,3,5,7,9,];
sum(list);

// 配列の合計を返す
function sum(arr) {
  var total = 0,
      len = arr.length;
  for (var i=0; i<len; i++) {
    total += arr[i];
  }
  return total;
}

4. .eslintrcの作成

コマンドでチェックしたいJSファイルが置かれた階層に移動して、
下記のように入力すると、ESLintでのチェックが行われます。

eslint <ファイル名>

しかし、設定ファイルである.eslintrcファイルを作成してチェック項目を設定しなければ、
上記のコマンドを入力しても実際にチェックは行われません。

そこで、チェックする予定のファイルと同階層に下記の内容の.eslintrcファイルを用意します。

{
    "extends": "eslint:recommended",
    "rules": {
        "no-unsafe-finally": "off",
        "no-native-reassign": "off",
        "complexity": ["off", 11],
        "comma-dangle": "error",
        "require-yield": "error"
    }
}

ドットで始まるファイル名が作成できない場合は、
FTP上でファイル名を変更するか、コマンドでrenameしてください。

ちなみに、上記の記述は「ESLintの推奨設定でチェックする」という記述です。
下記のページのチェックアイコンが付いた項目がチェック対象となります。

List of available rules - ESLint - Pluggable JavaScript linter
・(推奨設定の日本語訳) eslint-recommended.md

今後チェック項目をカスタマイズしたい場合は、こちらの.eslitrcファイルを編集することになります。

5. コマンドで再チェック

チェック項目を設定しましたので、もう一度チェックしてみましょう。

eslint <ファイル名>

すると下記のような内容が表示されました。
これは、1行目の配列の末尾に不要なカンマがあることを表しています。

1:21 error Unexpected trailing comma comma-dangle

✖ 1 problem (1 error, 0 warnings)

チェック内容に違反する箇所がある場合、
一つ一つのエラーは下記のフォーマットで順に表示されます。

行数:列数 [error/warning] [エラー文言] [チェックに使用したルール]

これらのリストの後、最終行に問題がいくつあるのか、
そのうちerrorとwarningがいくつあるのかが表示されます。

ESLintの基本的な使い方は以上です。
これで最低限の構文チェックをJSファイルに対して行うことができるようになりました。

チェック内容のカスタマイズ

個別にチェック内容を設定する(rulesキーの設定)

ESLint の最大の特徴はチェック内容を柔軟にカスタマイズできる点にあります。
チェック内容は.eslintrcに記載しますので、.eslintrcの詳しい記述方法について確認します。

.eslintrcはJSONかYAML形式で記述が可能です。
この記事では全てJSON形式で記述しています。

ESLint の推奨設定の書き方は先に紹介しましたが、
個別にチェック内容を設定したい場合は、下記のようにrulesキーに項目を追加します。

{
  "rules": {
    "curly": 2
  }
}

curlyは制御文で中括弧が使用されているかどうかをチェックします。
上の例では値が「2」となっていますが、各チェック項目共通で下記の値を設定できます。

0 or "off":チェックしない
1 or "warn":チェックする(違反するとwarningと判定)
2 or "error":チェックする(違反するとerrorと判定)

つまり、上の設定例では、下記のようなソースでは全てerrorとなります。

if (foo) foo++;

while (bar)
    baz();

if (foo) {
    baz();
} else qux();

エラーの内容を確認すると、各行の最後にcurlyとありますので、
このエラーがcurlyのチェック内容に引っ掛かったために発生していることがわかります。

1:1 error Expected { after 'if' condition curly
3:1 error Expected { after 'while' condition curly
8:3 error Expected { after 'else' curly

エラーの発生しているソースは、それぞれ下記のように修正するとerrorは発生しなくなります。

if (foo) {
    foo++;
}

while (bar) {
    baz();
}

if (foo) {
    baz();
} else {
    qux();
}

こちらに記載したソースは次のページのソースを流用しています。

Rule curly - ESLint - Pluggable JavaScript linter

各チェック項目毎にこのようなドキュメントが用意されており、
他のツールに比べてもドキュメントが充実していることがESLintの長所でもあります。

特定の環境下やライブラリが読み込まれていることが前提でチェックを行う。(envキーの設定)

今度は先ほどの.eslintrcにno-undefを追加してみます。
これは未定義の変数があるかどうかを確認するチェック項目です。

{
  "rules": {
    "curly": 2,
    "no-undef": 2
  }
}

このチェック項目で下記のようなjsファイルをチェックしてみます。

foo = 'test';

すると下記のようにエラーが表示されました。
no-undefのチェックで'foo'が未定義であることがわかります。

1:1 error 'foo' is not defined no-undef

では、次のjsファイルではどうでしょうか。

$(function(){
 window.alert('test');
});

$はjQueryオブジェクトの参照を表す変数、
windowはwindowのブラウザオブジェクトを表しますが、共にjsファイルのソースのみでは定義済みと判断できないのでエラーが発生しています。

1:1 error '$' is not defined no-undef
2:2 error 'window' is not defined no-undef

このエラーの発生は動作としては正しいのですが、windowはブラウザに組み込まれているオブジェクトですし、
jQueryは通常同じページ内の別ファイルから読み込まれていますので、このエラーを表示させる必要はありません。

そこで、下記のようにenvキーに記述を追加することで、
指定した環境下で使用される変数をチェック対象から除外してくれます。

{
  "env": {
      "browser": true,
      "jquery": true
  },
  "rules": {
    "curly": 2,
    "no-undef": 2
  }
}

こちらで再度チェックすると、エラーは発生しません。

ESLint は様々な環境下での使用に対応しています。
envキーに設定できる項目の詳細は下記をご確認ください。

Configuring ESLint - ESLint - Pluggable JavaScript linter

独自の変数をチェック対象外にしたい(globalsキーの設定)

jQueryや組み込みオブジェクトなどと違って、ユーザーがチェック対象外の変数を独自に設定したい場合は、globalsキーを使用します。
次の設定では 変数fooとbarを定義済みの変数として扱うよう記述しています。

{
  "globals": {
    "foo": true,
    "bar": true
  }
}

エディタとの連携

ここまではコマンドでチェックを行ってきましたが、
主要なエディタと連携し、作業をしながら随時チェックすることも可能です。

SublimeText

Package Controlから下記のパッケージをインストールします。
・SublimeLinter
・SublimeLinter-eslint

メニュー[Tools(ツール)]→[SublimeLinter]→[Debug Mode]にチェックが入っていなければチェックを入れます。

これでJSファイルを編集している最中に行数の左側にerrorやwarningの発生状況が確認できます。
エラーが発生しているソースにカーソルを合わせると、ステータスバーにエラーの詳細が表示されます。

SublimeTextのスクリーンショット

Atom

メニュー[ファイル]→[環境設定]で左ナビから[インストール]をクリックし、
下記のパッケージをインストールします。
・linter-eslint

Atomのスクリーンショット

Brackets

メニュー[ファイル]→[拡張機能マネージャー]から下記のエクステンションをインストールします。
・Interactive Linter

Bracketsのスクリーンショット

まとめ

JavaScriptの構文チェックツールは名前が似通っていることもあり、
それぞれがどう違うのか、よくわかっていないところがありましたので、
今回調べてみることで整理ができました。

また、このようなツールは最初は面倒に感じても、
とにかく使ってみることが習慣化につながると思いますので、
使い始めるまでの手順に重点を置いてまとめてみました。

機会があれば次回、
・JSLint, JSHintからの移行
・有名なスタイルガイドのチェック項目でチェック
・各種ツール(gulp、Gitなど)との連携
など今回紹介できなかった項目について引き続きまとめてみたいと思います。

▼新しい記事を公開しました

ESLintを使ったJavaScriptの検証をGitやGulpで自動化する

参考

JSLint から JSHint をフォークした理由 ― アントン・コヴァリャノフ | 黒くないすべてのものはカラスではない
ESLint 0.1.0がリリースされたので、JSHintとの違いやプラグインの書き方について | Web Scratch
時代はESLint。JSLintでもJSHintでもなくESLint。 - Qiita
ESLint 最初の一歩 - Qiita
など

お問い合わせはこちら