LoginSignup
152
95

More than 3 years have passed since last update.

ESLint v7.0.0 の変更点まとめ

Last updated at Posted at 2020-05-08

v6.8.0 | 次 v7.1.0

ESLint 7.0.0 がリリースされました。
多数の互換性のない変更、ルール追加、オプション追加、そしてバグ修正が含まれています。

以下は主要な変更点のまとめです。

ユーザー向けの変更:

プラグイン開発者向けの変更:

ツール開発者 (エディタ拡張等) 向けの変更:

質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。

🏢 日本語 Issue 管理リポジトリ
👫 日本語サポート チャット (招待リンク)
🏢 本家リポジトリ
👫 本家サポート チャット (招待リンク)


[PR] ESLint は開発リソースを確保するための寄付を募っています。
応援してくださると嬉しいです。

💥 互換性がない変更

Node.js 8.x/11.x のサポートを終了します

🔖 RFC044, #12700

Node.js 8.x は 2019-12-31 に、11.x は 2019-06-01 に寿命を迎えたため、ESLint もそれらのバージョンのサポートを停止しました。

ESLint 7.0.0 がサポートする Node.js のバージョンは ^10.12.0 || >=12.0.0 となります。

動作を元に戻したい場合:

この変更は元に戻せません。
古い Node.js 環境をアップグレードするまで ESLint 7 を利用しないようにしてください。

overrides 設定に一致するファイルを自動的にリント対象にします

🔖 RFC020, #12677

これまで、eslint lib のようにディレクトリを指定したとき、ESLint はディレクトリ内の *.js ファイルをチェックしていました。Node.js が *.cjs/*.mjs 拡張子を導入したり、TypeScript や Vue.js でも ESLint を使うようになったりしたので、この仕様は不便でした。

ESLint 7.0.0 からは *.js に加えて overrides 設定にマッチするファイルもチェックします。例えば、

.eslintrc.yml
overrides:
- files: "*.js"
  extends: my-config-js
- files: "*.ts"
  extends: my-config-ts

のような設定がある場合、eslint lib コマンドは lib ディレクトリ内の *.ts ファイルもチェックします。

なお、eslint lib/** のように Glob パターンを指定した場合は今まで通りに動作しますのでご注意ください。overrides 設定にかかわらず Glob パターンにマッチする全てのファイルをチェックします。

プラグイン開発者へ:

あなたが管理するプラグインが *.js 以外のファイルを対象にするルールを提供する場合、recommended設定に overrides を追加すると利用者は便利かもしれません。

動作を元に戻したい場合:

今まで通り overrides 設定にかかわらず *.js だけをチェックしたい場合は、コマンドに --ext js を付与してください。--ext CLI オプションはこの新しい動作を上書きします。

--config CLI オプションによる設定ファイル内の相対パスの扱いが変わります

🔖 RFC037, #12887

ignorePatterns, overrides[].files, overrides[].excludedFiles 設定に相対パスがあった場合、その相対パスは設定ファイルの場所を基準に解決されます (共有設定内のそれら相対パスは、利用元の.eslintrc.*ファイルの場所を基準に解決されます)。

ESLint 7 でも基本的には同様です。しかし、--config CLI オプションで読み込んだファイルのみ、それら相対パスは CWD を基準に解決されるようになります。これは CWD にある仮想的な .eslintrc.* ファイルから extends されたのと同じ動作になります。

動作を元に戻したい場合:

この変更は元に戻せません。
もし、この変更が原因で意図しない挙動になった場合は、設定ファイル内の相対パスを書き換えてください。

--ignore-path CLI オプションによる無視ファイル内のパスの扱いが変わります

🔖 RFC037, #12887

.eslintignore ファイル内のパスは、そのファイルの場所を基準に解決されます。

ESLint 7 でも基本的には同様です。しかし、--ignore-path CLI オプションで読み込んだファイルのみ、それらパスは CWD を基準に解決されるようになります。

動作を元に戻したい場合:

この変更は元に戻せません。
もし、この変更が原因で意図しない挙動になった場合は、無視ファイル内のパスを書き換えてください。

プラグインの読込元ディレクトリが変わります

🔖 RFC047, #12922

ESLint 6 はすべての設定ファイルに書かれた plugins 設定のプラグインを $CWD/node_modules ディレクトリから読み込みます。この動作のため、エディタ拡張等に適切な CWD を設定しなければプラグインを利用できず、Monorepo スタイルの開発などで不便でした。

ESLint 7 では、設定ファイルに書かれた plugins 設定のプラグインは、各設定ファイルの場所を基準に読み込まれます。つまり、packages/alice/.eslintrc.yml ファイルに書かれたプラグインは packages/alice/node_modules ディレクトリから読み込まれます。

⚠️ 共有設定に書かれた plugins 設定のプラグインは、それを extends する利用元の .eslintrc.* ファイルの場所を基準に読み込まれます。そのため、共有設定からプラグインを利用する場合は引き続き peerDependencies を利用する必要があります。

動作を元に戻したい場合:

以前と同様に $CWD/node_modules ディレクトリからすべてのプラグインを読み込みたい場合は --resolve-plugins-relative-to . CLI オプションを利用してください (末尾のドットに注意)。
--resolve-plugins-relative-to CLI オプションはこの新しい動作を上書きします。

デフォルトで無視するファイルが変わります

🔖 RFC051, #12888

ESLint 6 がデフォルトで無視するファイルは、以下のパターンにマッチするファイルでした。

  • .* (dotfiles)
  • /node_modules/** (CWD にある node_modules ディレクトリ内)
  • /bower_components/** (CWD にある bower_components ディレクトリ内)

ESLint 7 では、以下のように変更されます。

  • .!(eslintrc.*) (.eslintrc.* 設定ファイルを除く dotfiles)
  • /**/node_modules/** (node_modules ディレクトリ内)

動作を元に戻したい場合:

以前のように .eslintrc.*/bower_components/** を無視したい、またはサブディレクトリの node_modules ディレクトリを無視したくない場合、.eslintrc.* 設定ファイルの ignorePatterns 設定を利用してください。

.eslintrc.yml
ignorePatterns:
- "!/*/**/node_modules/*"
- ".eslintrc.*"
- "/bower_components/*"

ディレクティブコメントに説明を書けます

🔖 RFC033, #12699

ディレクティブコメントとは、/* eslint-disable */ のような ESLint の動作変更を指示するためのコメントのことです。ルールを無効にする場合、その理由を明示しておくことは良いことです。しかし、ディレクティブコメントの理由を書くための標準的な方法はありませんでした。

ESLint 7 では、空白文字に囲まれた2つ以上のハイフン -- を使ってディレクティブコメントに説明を追加できます。


/* eslint-disable a-rule -- このルールはバグっている */
doSomething()

/* eslint-disable another-rule
----------------
ここでは...(略
 */

動作を元に戻したい場合:

この変更は元に戻せません。
もし、既存のディレクティブコメントに--が含まれていて壊れてしまった場合は、その設定を設定ファイルの overrides 等に移してください。

eslint:recommended設定が有効にするルールが増えます

🔖 #12920

新たに 3 つのルールが有効になります。

  • no-dupe-else-if ... if-else if チェーンにおいて、前の if 文の条件を満たすために絶対に真にならない if 文を報告します。
  • no-import-assign ... import 文で作成した変数への代入 (実行時エラーになる) を報告します。
  • no-setter-return ... セッター内にある値を返す return を報告します。

動作を元に戻したい場合:

上記ルールを有効にしたくない場合は、設定ファイルに無効化する設定を追加してください。

extends: eslint:recommended
rules:
  no-dupe-else-if: "off"
  no-import-assign: "off"
  no-setter-return: "off"

複数のルールのチェックが厳しくなります

🔖 #12195, #12490, #12608, #12701, #12757, #12765, #12806, #12816, #12837, #12876, #12913, #12915, #12919, #12927

以下のルールはより多くのエラーを報告するようになりました。

  • accessor-pairs ... オブジェクト リテラルだけでなく、クラス メンバーもチェックするようになりました。
  • array-callback-return ... ES2019 で追加された flatMap() メソッドもチェックするようになりました。
  • computed-property-spacing ... オブジェクト リテラルだけでなく、クラス メンバーもチェックするようになりました。
  • func-names ... デフォルト エクスポートの関数宣言も名前が省略可能であるため、関数式と同じように名前の有無をチェックするようになりました。
  • no-constant-condition ... 埋込式がないか、全ての埋込式が定数であるテンプレートリテラルも定数であると認識するようになりました。
  • no-dupe-class-members ... 計算されたプロパティ名が定数だった場合は重複チェックをするようになりました。
  • no-extra-parens ... 代入演算子の左側についてもカッコの有無をチェックするようになりました。
  • no-implied-eval ... window.evalのようなグローバルオブジェクトのプロパティアクセスも認識するようになりました。
  • no-iterator ... 計算されたプロパティ名が定数だった場合も認識するようになりました。
  • no-magic-numbers ... BigInt リテラルも認識するようになりました。
  • no-proto ... 計算されたプロパティ名が定数だった場合も認識するようになりました。
  • no-restricted-modules ... 埋込式がないか、全ての埋込式が定数であるテンプレートリテラルも定数であると認識するようになりました。
  • quote-props ... プロパティ名としての BigInt リテラルも認識するようになりました。
  • radix ... parseInt() 関数の第二引数が無効な数値 (2未満 or 36より大きい) の場合もエラーを報告するようになりました。
  • use-isnan ... case 句の NaN もエラー報告するようになりました。
  • yoda ... BigInt リテラルとテンプレートリテラルも認識するようになりました。

他にもあるかも...

動作を元に戻したい場合:

この変更は元に戻せません。
もし、新しくエラーが報告された場合はコードを修正してください。

複数の Node.js/CommonJS 向けルールが廃止されます

🔖 #12898

Node.js/CommonJS 向けのルールが非推奨になりました。
代わりに eslint-plugin-node の対応するルールをご利用ください。

非推奨 代わりのルール
callback-return node/callback-return
global-require node/global-require
handle-callback-err node/handle-callback-err
no-mixed-requires node/no-mixed-requires
no-new-require node/no-new-require
no-path-concat node/no-path-concat
no-process-env node/no-process-env
no-process-exit node/no-process-exit
no-restricted-modules node/no-restricted-require
no-sync node/no-sync

動作を元に戻したい場合:

廃止されたルールは引き続き利用することができます。
ただし、廃止されたルールのコードは凍結され、今後はバグ修正や機能追加が行われません。早めの移行をお勧めします。

個人設定の利用がランタイム警告を出力します

🔖 RFC032, #12678

個人設定とは、OS のホームディレクトリ (例: /home/foo/, C:\Users\foo\) に配置された .eslintrc.* 設定ファイルのことです。ESLint はプロジェクト内に設定ファイルが見つかると個人設定を (親ディレクトリであっても) 無視し、プロジェクト内に設定ファイルが見つからないと個人設定を (親ディレクトリでなくても) 利用します。

この個人設定の仕組みは ESLint 6.7.0 で非推奨になりました

ESLint 7 では、個人設定の仕組みを利用すると標準エラー出力に非推奨警告を出力するようになります。

動作を元に戻したい場合:

この変更は元に戻せません。
もし、引き続きホームディレクトリの設定を利用したい場合は、--config CLI オプションで利用する設定を明示的に指定してください。もしくは、ホームディレクトリ以下に作業ディレクトリを作ってください (ESLint は親ディレクトリからも設定ファイルを探すので)。

RuleTester のチェックが厳しくなります

🔖 RFC025, #12096, #12955

RuleTester がより多くの誤りを見つけるようになります。

  • ルールが非標準の node.start/node.end プロパティを参照していた場合にテストが失敗するようになります。代わりに node.range プロパティを利用してください。
  • ルールが自動修正を提供するにもかかわらず、自動修正のテスト (output) が書かれていない場合にテストが失敗するようになります。
  • 期待されるエラー内容を指示するerrorsプロパティ内に未知のプロパティがあったとき、テストが失敗するようになります (typo でテストできてなかったという事がなくなります)。

動作を元に戻したい場合:

この変更は元に戻せません。
もし、新たにテストが失敗するようになった場合は、そのルールの処理かテスト内容を更新してください。

新しい ESLint クラスが CLIEngine クラスを置き換えます

🔖 RFC040, #12939

Node.js アプリケーションから ESLint を利用するための API として CLIEngine クラスが提供されています。しかし、CLIEngine クラスは同期 API を提供するため、非同期の処理が必要な並列処理・ES Modules サポート・進捗表示などの機能追加の妨げになっていました。
また、CLIEngine という名前は最初に使うべきクラスであるとの印象を抱きにくく、ブラウザ向けの機能限定版 API である Linter クラスを先に試して「意図通りに動かない」と issue を作る人が多かったです。

ESLint 7 では、この CLIEngine クラスを廃止して、後継となる ESLint クラスを導入しました。ESLint クラスは CLIEngine と同等のメソッドを提供しますが、Promise を返す非同期メソッドになっています。メソッドの対応は以下の通りです。

CLIEngine ESLint
executeOnFiles(patterns) lintFiles(patterns)
executeOnText(text, filePath, warnIgnored) lintText(text, options)
getFormatter(name) loadFormatter(name)
getConfigForFile(filePath) calculateConfigForFile(filePath)
isPathIgnored(filePath) isPathIgnored(filePath)
static outputFixes(results) static outputFixes(results)
static getErrorResults(results) static getErrorResults(results)
static getFormatter(name) (削除)
addPlugin(pluginId, definition) plugins コンストラクタ オプション
getRules() (未実装)
resolveFileGlobPatterns() (削除)

動作を元に戻したい場合:

現在 CLIEngine クラスは広く利用されているため、少なくとも1年間は削除されないはずです。引き続き利用することができます。
しかし、今後 CLIEngine のコードは凍結され、バグ修正や機能追加が行われません。例えば、ESLint 7.x では並列処理・ES Modules サポート・進捗表示の機能が追加される予定ですが、それらは ESLint クラスのみに実装され、CLIEngine クラスからは利用できません。早めの移行をお勧めします。

✨ 本体への機能追加

RuleTestersuggestionsテストでmessageId/dataを利用できます

🔖 #12635

RuleTestersuggestionsのテストにて、messageプロパティの代わりにmessageId/dataプロパティペアを用いてテストできるようになりました。

const { RuleTester } = require("eslint")
const rule = require("../../../lib/rules/a-rule")

new RuleTester("a-rule", rule, {
    valid: [],
    invalid: [
        {
            code: "foo",
            errors: [{
                messageId: "error",
                data: { name: "foo" },
                suggestions: [{
                    messageId: "suggest",
                    data: { name: "foo" },
                    output: "bar"
                }],
            }],
        },
    ],
})

💡 新しいルール

default-case-last

🔖 #12668

default句をswitch文の末尾以外に書くことを禁止するルールが追加されました。

/*eslint default-case-last: error */

//✘ BAD
switch (foo) {
  default:
    break
  case 0:
    break
  case 1:
    break
}

» Online Demo

no-restricted-exports

🔖 #12546

特定の名前の ES Modules エクスポートを禁止するルールが追加されました。

/*eslint no-restricted-exports: [error, { restrictedNamedExports: [foo, bar] }] */

//✘ BAD
export function foo() {}
let bar = 0
export { bar }

» Online Demo

no-useless-backreference

🔖 #12690

正規表現中の無意味な後方参照を禁止するルールが追加されました。

/*eslint no-useless-backreference: error */

//✘ BAD
let a = /foo\1(bar)/

» Online Demo

🔧 オプションが追加されたルール

array-callback-return: checkForEach

🔖 #12646

forEach()メソッドのコールバックについてもreturn文をチェックするオプションが追加されました。

/*eslint array-callback-return: [error, { checkForEach: true }] */

//✘ BAD
list.forEach(x => {
    return x * 2
})
list.forEach(x => x * 2)

//✔ GOOD
list.forEach(x => {
    x * 2
})

» Online Demo

array-element-newline: ArrayExpression and ArrayPattern

🔖 #11796

配列リテラルと分割代入の配列パターンとで別々の設定を行うためのオプションが追加されました。

/*eslint array-element-newline: [error, { ArrayExpression: always, ArrayPattern: never }] */

//✘ BAD
let foo = [1, 2]
let [
    a,
    b
] = foo

» Online Demo

indent: offsetTernaryExpressions

🔖 #12556

三項演算子の2項目と3項目のインデントをつけるオプションが追加されました。

/*eslint indent: [error, 4, { offsetTernaryExpressions: true }] */

//✘ BAD
let foo = cond
    ? () => {
        doSomething()
    }
    : () => {
        doSomething()
    }

//✔ GOOD
let bar = cond
    ? () => {
            doSomething()
        }
    : () => {
            doSomething()
        }

» Online Demo

indent: outerIIFEBody:"off"

🔖 #12706

トップレベルの即時関数呼び出しのインデントを検証しないオプションが追加されました。

/*eslint indent: [error, 4, { outerIIFEBody: "off" }]*/

//✔ GOOD
(function() {

function foo(x) {
    return x + 1;
}

})();

» Online Demo

no-extra-boolean-cast: enforceForLogicalOperands

🔖 #12734

論理式のオペランドでも不要な明示的な boolean 型変換を禁止するオプションが追加されました。

/*eslint no-extra-boolean-cast: [error, { enforceForLogicalOperands: true }] */

//✘ BAD
if (!!bar || Boolean(baz)) ;

» Online Demo

no-magic-numbers: BigInt in the ignore option

🔖 #12701

ignoreオプションが新たに文字列を受け入れるようになりました。各文字列は BigInt リテラルとして有効な文字列である必要があります。

/*eslint no-magic-numbers: [error, { ignore: ["123n"] }] */

//✔ GOOD
if (foo === 123n) ;

//✘ BAD
if (foo === 456n) ;

» Online Demo

no-void: allowAsStatement

🔖 #12613

式文の最初に書くvoid式を許可するオプションが追加されました。

/*eslint no-void: [error, { allowAsStatement: true }] */

//✔ GOOD
void doSomething()
void (async () => {
    doSomething()
})().catch(handleError)

//✘ BAD
let a = void doSomething()

» Online Demo


152
95
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
152
95