こんにちは。
ESLint のメンテナ1や npm-run-all 等 npm-scripts 向け CLI ツールの開発をしている @mysticatea です。
今回は Node.js アドベント カレンダーということで、eslint-plugin-node を紹介したいと思います。
eslint-plugin-node は、Node.js 向けに特化した ESLint の追加ルールを定義しているプラグインです。
ESLint 本体に付属しているルール群 (通称コアルール) にも Node.js に特化したものがありますが、このプラグインのルールは諸事情2によりコアに入れなかったルールたちです。
ESLint 自体についてはこちらの記事をご覧ください。
インストール
ESLint プラグインですので、npm を利用してインストールします。
ESLint をグローバル (--global
) にインストールしている場合は、同じくグローバルへ。ESLint をローカル (--save-dev
) にインストールしている場合は、同じくローカルへインストールしてください。
$ npm install --save-dev eslint eslint-plugin-node
- Node.js 4.0.0 以降が必要です。
- ESLint 3.1.0 以降が必要です。
なお、推奨はローカル インストールです。
設定の書き方
.eslintrc.json
等の設定ファイルにプラグインの情報を書く必要があります。
{
"extends": ["eslint:recommended"],
"plugins": ["node"],
"env": {
"es6": true,
"node": true
},
"rules": {
"node/exports-style": "error", //`module.exports`と`exports.*`を混ぜて使うと警告します。
"node/no-deprecated-api": "error", //Node.jsの非推奨APIを使用すると警告します。
"node/no-missing-import": "error", //`import`構文で存在しないファイルを読もうとすると警告します。
"node/no-missing-require": "error", //`require()`で存在しないファイルを読もうとすると警告します。
"node/no-unpublished-bin": "error", //CLIのエントリポイントが無視リストに入っていた場合に警告します。
"node/no-unpublished-import": "error", //`import`構文で公開後に読めなくなるモジュールを読もうとすると警告します。
"node/no-unpublished-require": "error", //`require()`で公開後に読めなくなるモジュールを読もうとすると警告します。
"node/no-unsupported-features": "error", //指定したNode.jsのバージョンでサポートされていない構文を使おうとすると警告します。
"node/process-exit-as-throw": "error", //`process.exit()`の実行パスを修正します。
"node/shebang": "error", //シバンの誤りを指摘します。
}
}
ルール説明
node/exports-style
Node.js でクラスや関数をファイル外にエクスポートするとき、module.exports
と exports
を混在させて使おうとすると、予期せぬ事態になる可能性があります。
module.exports = function foo() {
// do something.
}
exports.foo = 1
この時、exports.foo
はエクスポートされず消えてしまいます。
こういった事態を抑止するために、module.exports
と exports
のうち、指定した方だけを利用するように設定することができます。
{
"node/exports-style": ["error", "module.exports"],
//または
"node/exports-style": ["error", "exports"]
}
//✔ GOOD
module.exports = {
foo: 1,
bar: 2
}
module.exports.baz = 3
//✘ BAD
exports.qiz = 4
//✔ GOOD
exports.foo = 1
exports.bar = 2
exports.baz = 3
//✘ BAD
module.exports = {}
node/no-deprecated-api
Node.js の非推奨 API を利用しようとすると警告します。
{
"node/no-deprecated-api": "error",
}
//✘ BAD
fs.exists(fileName, (b) => {})
const b = new Buffer(text)
非推奨 API には、将来的に削除される予定のものや、セキュリティ リスクのあるもの等が存在します。
ぜひ避けましょう。
警告される API の一覧はこちら。
node/no-missing-require
require()
式で存在しないファイル/モジュールをインポートしようとすると警告します。
モジュール名やファイルパスの打ち間違えに素早く気がつくことができます。
{
"node/no-missing-require": "error",
}
//✘ BAD
const typoFile = require("./typo-file");
const typoModule = require("typo-module");
node/no-missing-import
node/no-missing-require
と同じですが、require()
式の代わりにimport
構文をチェックします。
ECMAScript 2015 (ES6) ではファイルの検索ロジックは定義されておらず、Node.js はまだ ES Modules 構文をサポートしていません。そのため、このルールは将来的に変更される可能性があります。
node/no-unpublished-bin
CLI のエントリポイントが無視リストに入っていた場合に警告します。
-
npm publish
でモジュールを公開する時、不要なファイルは含めないように設定しておくことが望ましいです。package.json
の files フィールドや .npmignore ファイルを利用して、モジュールに含めるファイル・含めないファイルを指定することができます。 - 各モジュールは
package.json
の bin フィールドを使って CLI コマンドを公開することができます (例えばeslint
コマンドはこの機能で公開されています)。
さて、npm は package.json
の bin フィールドで指定されているファイルを自動的にモジュールに含めてくれません。そのファイルが files フィールドに含まれていなかったり、.npmignore ファイルに含まれていたりすると除外され、利用者がモジュールをインストールしようとしたときにエラーになります。
{
"name": "my-module",
"version": "1.0.0",
"bin": "bin/index.js",
"files": ["lib"] //※binディレクトリを含めていない
}
このようなエラーを事前に見つけて報告してくれます。
node/no-unpublished-require
モジュール公開後に読めなくなるファイルをrequire()
式でインポートしようとすると警告します。
このルールは、次のようなシチュエーションを防ぎます。
- 開発環境では動くが、モジュール公開後に読み込もうとしたファイル・モジュールが存在せずエラーになる
- あなたのローカル環境では動くが、チームメンバーが
clone
すると読み込もうとしたファイル・モジュールが存在せずエラーになる
これらを回避するために、次のようなrequire()
式を警告します。
-
require()
式が公開されるファイル3に書かれている場合- インポート対象が公開されないファイル4である
- インポート対象が
package.json
のdependencies
フィールドに含まれないモジュールである
-
require()
式が公開されないファイルに書かれている場合- インポート対象が
package.json
のdependencies
/devDependencies
両フィールドに含まれないモジュールである
- インポート対象が
babel 等のトランスパイラを利用している場合、ソースコードの位置とトランスパイル後のファイルの位置が異なる可能性があります。この場合は convertPath オプションを使うと適切な警告を生成できます。
node/no-unpublished-import
node/no-unpublished-require
と同じですが、require()
式の代わりにimport
構文をチェックします。
ECMAScript 2015 (ES6) ではファイルの検索ロジックは定義されておらず、Node.js はまだ ES Modules 構文をサポートしていません。そのため、このルールは将来的に変更される可能性があります。
node/no-unsupported-features
指定した Node.js のバージョンでサポートされていない ECMAScript 構文を使おうとすると警告します。
例えば、Node.js 4 は (strict モードの外では) let
,const
,class
をサポートしていません。一方で、"use strict"
が適切に書かれていればlet
,const
,class
を使うことができます。
- より詳しくは node.green をチェックしてください。
このルールを使うと、未サポートの構文を使おうとしてしまった場合に素早く気がつくことができます。
どのバージョンを対象にするか? は、package.json
の engines フィールドによって指定します。
{
"name": "my-module",
"version": "1.0.0",
"engines": {
"node": ">=4.0.0"
}
}
node/process-exit-as-throw
process.exit()
の実行パスを修正します。
実行パス解析を利用した静的検証を改善するメタルールです。
このルール自体は何も警告しませんが、process.exit()
式がthrow
文と同等に扱われるように実行パス解析を修正することにより、実行パス解析を利用するルールの誤検出を軽減します。
例えば、次のコードにこのメタルールを有効にすることで consistent-return ルールの誤検出が修正されます。
function foo(a) { //※ error 値を返さない実行パスがあります (Expected to return a value at the end of this function.)
if (a) {
return "ok"
} else {
process.exit(1)
}
}
node/shebang
シバンの誤りを指摘します。
各モジュールは package.json
の bin フィールドを使って CLI コマンドを公開することができます。
この時、CLI コマンドとして実行される .js
ファイルにはシバンを書くことになります。
#!/usr/bin/env node
console.log("hello")
このようにすると、npm はこのファイルを Linux でも Windows でも実行できるように適切にインストールしてくれます。
このルールは、eslint --fix
による自動修正でシバンを自動的に追加します。
あとがき
エディタに連携させてリアルタイムで警告が表示されるようにしたら、作業がより捗るのではないでしょうか。私見ですが、ESLint と相性が良いエディタはずばり Visual Studio Code です。
ESLint は起動が遅いのですが、Visual Studio Code は Node.js を内蔵しているために ESLint をエディタ内で実行できます。毎回起動しなくて良いので驚くほど軽快です。おすすめ。
それでは、良き開発ライフを 。
-
ファイルシステムを使う必要があったり、メンテナンス コストが高かったり ↩
-
package.json
の files フィールドに含まれていて、かつ .npmignore ファイルに含まれていないファイル ↩ -
package.json
の files フィールドに含まれていないか、または .npmignore ファイルに含まれているファイル ↩