Closed6

ESLint Flat Config を ESM (.mjs) で書く

teppeisteppeis

ESLintの新しいFlat Configは、デフォルトではファイル名と拡張子が固定でeslint.config.jsしか使えない。eslint.config.mjsが使えない。
つまり、プロジェクトのpackage.jsontypeに依存して、中身がCommonJSかESMなのかが変わってしまう。
https://eslint.org/docs/latest/use/configure/configuration-files-new

これは実際けっこう面倒になりそうで、自分で使う設定ファイルは共通で使い回すことになると思うけど、プロジェクトによってrequire()を使うCJS用とimportを使うESM用で書き分けないといけなくなる。

一応コマンドライン引数を使えば任意のファイル名を設定ファイルとして渡すことはできるけど、その場合は環境変数でFlat Configを有効化する必要もあるので、都度手で打つのは厳しい長々としたコマンドになってしまう。

ESLINT_USE_FLAT_CONFIG=true eslint -c eslint.config.mjs

ESLintチームは、これに関してかなり固い決意を持っているようなので覆らなそう。

対応方法

ということで、今のところこんな感じで対応しようと思っている。

  • まず設定ファイル本体はESMで書く
  • プロジェクトがtype:moduleの場合、その設定ファイルをそのままeslint.config.jsとして設置
  • プロジェクトがtype:commonjsの場合、設定ファイルをeslint.config.mjsとして設置した上で、別途eslint.config.jsから以下のようにproxyっぽく参照する。
eslint.config.js
module.exports = import("./eslint.config.mjs").then((n) => n.default);

eslint.config.jsPromiseを扱えるので、module.exportsimport()の結果を直接返して問題ない。

背景

上でも触れたけど、現状、Flat Configを使う方法は以下の2つが存在する。

  • eslint.config.jsというファイルが存在する
  • 環境変数でFlat Configを有効化した上で、コマンドライン引数で設定ファイルを指定
    • ex) ESLINT_USE_FLAT_CONFIG=true eslint -c eslint.config.mjs

後者は手動で指定するのも面倒だし、エディタやCI等との連携で設定の手数が増えるのもダルい。なので、こういう参照するだけのeslint.config.jsを置いてしまった方が楽だと思う。デフォルトがFlat Configになるのはまだだいぶ先っぽいので、これでしばらくやってみる。

teppeisteppeis

そもそもの話。

過去に.eslintrcをJS, JSON, YAMLなど多数のフォーマットに対応して複雑化した反省から、ESLintコアチームが対応拡張子を増やしたくないというのは気持ちはわかる。

しかし、.mjs, .cjs対応はしてもいいんじゃないかと個人的には思う。.jsしか対応しないと言っても、中身としてはすでにESMとCJSの両対応はしちゃってるわけで、それの拡張子の扱いが変わるだけでそこまで複雑さは増さないと思うんだけどなあ。ESMにしか対応しないっていうならわかるが。

もうissueはロックされてるから決意は固いんだろうけど。

teppeisteppeis

ESLintが方針変更して、eslint.config.mjs, eslint.config.cjsをサポートすることを決めた!

https://github.com/eslint/eslint/issues/17863

eslint.config.js, eslint.config.mjs, and eslint.config.cjs の順に探索するようになるらしい。

理由としては、DefinitelyTyped など巨大monorepoとの相性の悪さと、VS Codeなどエディタ設定でCLIオプションをいちいち変更することの煩雑さ。特に後者は現実的でないので、ようやく気づいてくれた感。

年末にアルファを出すらしいので、近いうちに上で書いたtipsも不要になりそう。良かった。

このスクラップは2023/10/30にクローズされました