ESLint Flat Config を ESM (.mjs) で書く
ESLintの新しいFlat Configは、デフォルトではファイル名と拡張子が固定でeslint.config.js
しか使えない。eslint.config.mjs
が使えない。
つまり、プロジェクトのpackage.json
のtype
に依存して、中身がCommonJSかESMなのかが変わってしまう。
これは実際けっこう面倒になりそうで、自分で使う設定ファイルは共通で使い回すことになると思うけど、プロジェクトによってrequire()
を使うCJS用とimport
を使うESM用で書き分けないといけなくなる。
一応コマンドライン引数を使えば任意のファイル名を設定ファイルとして渡すことはできるけど、その場合は環境変数でFlat Configを有効化する必要もあるので、都度手で打つのは厳しい長々としたコマンドになってしまう。
ESLINT_USE_FLAT_CONFIG=true eslint -c eslint.config.mjs
ESLintチームは、これに関してかなり固い決意を持っているようなので覆らなそう。
- 2022-12-01 ESLint TSC Meeting Notes
- Bug: [flat config]
.mjs
extension for config file · Issue #16580 · eslint/eslint
対応方法
ということで、今のところこんな感じで対応しようと思っている。
- まず設定ファイル本体はESMで書く
- プロジェクトが
type:module
の場合、その設定ファイルをそのままeslint.config.js
として設置 - プロジェクトが
type:commonjs
の場合、設定ファイルをeslint.config.mjs
として設置した上で、別途eslint.config.js
から以下のようにproxyっぽく参照する。
module.exports = import("./eslint.config.mjs").then((n) => n.default);
eslint.config.js
はPromise
を扱えるので、module.exports
がimport()
の結果を直接返して問題ない。
背景
上でも触れたけど、現状、Flat Configを使う方法は以下の2つが存在する。
-
eslint.config.js
というファイルが存在する - 環境変数でFlat Configを有効化した上で、コマンドライン引数で設定ファイルを指定
- ex)
ESLINT_USE_FLAT_CONFIG=true eslint -c eslint.config.mjs
- ex)
後者は手動で指定するのも面倒だし、エディタやCI等との連携で設定の手数が増えるのもダルい。なので、こういう参照するだけのeslint.config.js
を置いてしまった方が楽だと思う。デフォルトがFlat Configになるのはまだだいぶ先っぽいので、これでしばらくやってみる。
そもそもの話。
過去に.eslintrcをJS, JSON, YAMLなど多数のフォーマットに対応して複雑化した反省から、ESLintコアチームが対応拡張子を増やしたくないというのは気持ちはわかる。
しかし、.mjs, .cjs対応はしてもいいんじゃないかと個人的には思う。.jsしか対応しないと言っても、中身としてはすでにESMとCJSの両対応はしちゃってるわけで、それの拡張子の扱いが変わるだけでそこまで複雑さは増さないと思うんだけどなあ。ESMにしか対応しないっていうならわかるが。
もうissueはロックされてるから決意は固いんだろうけど。
npx eslint-config-teppeis --init
で生成するようにした。
ESLintにパッチを当ててeslint.config.mjs
やeslint.config.ts
をロードさせるツールがantfuから出てきた
個人的には.ts
まではいらないが、.mjs
対応はうれしい。本家で何とぞ
ESLintが方針変更して、eslint.config.mjs
, eslint.config.cjs
をサポートすることを決めた!
eslint.config.js, eslint.config.mjs, and eslint.config.cjs の順に探索するようになるらしい。
理由としては、DefinitelyTyped など巨大monorepoとの相性の悪さと、VS Codeなどエディタ設定でCLIオプションをいちいち変更することの煩雑さ。特に後者は現実的でないので、ようやく気づいてくれた感。
年末にアルファを出すらしいので、近いうちに上で書いたtipsも不要になりそう。良かった。
v8.57.0にバックポートされて、.mjs, .cjsが使えるようになった。
Support for eslint.config.mjs and eslint.config.cjs