11
5

ESLintのFlat Configにマイグレーションしたメモ

Last updated at Posted at 2024-04-11

概要

前回はESLintの暫定対応を行った。
v8 -> v9 マイグレーションガイドでは難しそうに感じたが、ESLintのFlat Config移行でやって良かったことで紹介されているtypescript-eslintに従えばスムーズに進められそうだったのでmonorepoの設定を行ったリポジトリで対応した。

ソースコード

対応コミット

大きな変更点

typescript-eslintを導入し、@typescript-eslint/eslint-pluginは廃止した。

package.json
{
  "name": "@kartagraph/eslint-config-custom",
+  "type": "module",
  "private": true,
  "license": "MIT",
  "version": "0.0.0",
  "devDependencies": {
+    "@eslint/eslintrc": "^3.0.2",
+    "@eslint/js": "^9.0.0",
-    "@typescript-eslint/eslint-plugin": "^7.6.0",
-    "@typescript-eslint/parser": "^7.6.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-config-turbo": "^1.13.2",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.6",
    "eslint-plugin-unused-imports": "^3.1.0",
+    "typescript": "^5.4.5",
+    "typescript-eslint": "^7.6.0"
  },
  "scripts": {
+    "inspect": "npx @eslint/config-inspector",
    "ncu": "ncu -u"
  }
}

jsファイルは、大きく書き換えた。

package/eslint-config-custom/defaults.js
+ import js from '@eslint/js';
+ import tseslint from 'typescript-eslint';
+ import importPlugin from 'eslint-plugin-import';
+ import unuserdPlugin from 'eslint-plugin-unused-imports';

- module.exports = {
+ export default tseslint.config({

-  "extends": ["eslint:recommended","plugin:@typescript-eslint/recommended"],
+  extends: [js.configs.recommended, ...tseslint.configs.recommended],

- "plugins": ["import", "unused-imports"],
+  plugins: { import: importPlugin, 'unused-imports': unuserdPlugin },

  "rules": {
    "semi": ["error", "always"],
    "unused-imports/no-unused-imports": "warn", 
    "import/order": ["warn", { "groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"] // importの並び順の設定
                             , "pathGroupsExcludedImportTypes": ["builtin"]
                             , "pathGroups": [{ "pattern": "@src/**", "group": "parent", "position": "before"}] // エイリアスの位置を指定
                             , "alphabetize": { "order": "asc"} // グループ内のソート順
                             }
                    ]
  },
});

そのままではエラーが出るプラグインを移行する

エラーメッセージの例

Oops! Something went wrong! :(
ESLint: 9.0.0
A config object has a "plugins" key defined as an array of strings.
Oops! Something went wrong! :(
ESLint: 9.0.0
A config object is using the "extends" key, which is not supported in flat config system.

Using eslintrc Configs in Flat Configに書かれているFlatCompatを使用する。

import tseslint from 'typescript-eslint';
- import turboConfig from 'eslint-config-turbo';
+ import { FlatCompat } from "@eslint/eslintrc";
+ import path from "path";
+ import { fileURLToPath } from "url";

+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);

+ const compat = new FlatCompat({
+     baseDirectory: __dirname
+ });

export default tseslint.config({
   extends: [
     ...customConfig,
-    turboConfig,
+    ...compat.extends('eslint-config-turbo')
     prettierConfig
  ],

eslint-config-inspector

config-inspectorの出力をGithubActionsに組みたいが、v0.4.5ではIssueが出ているのでまだ難しそう。
これが解決したら出力できるようにしたい。

2024.04.25 追記 v0.4.7で出力できるようになった。

出力結果

Github Actions yaml
buildスクリプト package.json

(2024.04.22 追記) ESLint 9.1.0 にアップデートしたらエラーとなったメモ

現象

下記のエラーが出るようになった。

Oops! Something went wrong! :(

ESLint: 9.1.0

Error: 'patterns' must be a non-empty string or an array of non-empty strings

原因

前回ESLINT_USE_FLAT_CONFIG=falseにしていたものを戻していなかった。

対応

ESLINT_USE_FLAT_CONFIG=trueに変更する。

image.png

新たなエラー

ESLint: 9.1.0

Error: This method cannot be used with flat config. Add your entries directly into the config array.
    at assertEslintrcConfig (\node_modules\eslint\lib\linter\linter.js:1256:15)  
    at Linter.getRules (\node_modules\eslint\lib\linter\linter.js:2185:9)        
    at Object.<anonymous> (\node_modules\eslint-plugin-unused-imports\lib\rules\load-rule.js:10:32)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1206:32)
    at Module._load (node:internal/modules/cjs/loader:1022:12)
    at Module.require (node:internal/modules/cjs/loader:1231:19)
    at require (node:internal/modules/helpers:179:18)
o-unused-vars.js:11:14)

暫定対応

'eslint-plugin-unused-imports'をコメントアウトした。
しばらくこのプラグインが使えなくなるが、lintがまったく効かないよりましだと判断。
9.0.0に戻すこともあまりやりたくないので。

Issueは出ているので、待つこととしたい。 → 待ったら直った

packges/eslint-config-custom/default.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import importPlugin from 'eslint-plugin-import';
// import unuserdPlugin from 'eslint-plugin-unused-imports';

export default tseslint.config({
  extends: [js.configs.recommended, ...tseslint.configs.recommended],
  plugins: { import: importPlugin, 
    // 'unused-imports': unuserdPlugin
  },
  rules: {
    semi: ['error', 'always'],
    // 'unused-imports/no-unused-imports': 'warn',
    'import/order': [
      'warn',
      {
        groups: [ 'builtin','external','internal','parent','sibling','index','object','type' ], // importの並び順の設定
        pathGroupsExcludedImportTypes: ['builtin'],
        pathGroups: [ { pattern: '@src/**', group: 'parent', position: 'before' } ], // エイリアスの位置を指定
        alphabetize: { order: 'asc' }, // グループ内のソート順
      },
    ],
  },
});

moduleでないプロジェクトでの設定

下記のエラーがでるような場合。

SyntaxError: Cannot use import statement outside a module

eslint.config.js -> eslint.config.mjsに変更。

eslint 9.2.0に上げた時のメモ 2024.05.05 追記

eslint-plugin-unused-importsが使えるようになっていた。
この時点のソースコード

eslintの依存性エラーが出て試行錯誤したメモ。結局--legacy-peer-depsで解決

下記のエラーがでた。

npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@9.0.0
npm WARN node_modules/eslint
npm WARN   dev eslint@"^9.2.0" from the root project
npm WARN   5 more (@eslint-community/eslint-utils, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" from eslint-plugin-import@2.29.1
npm WARN node_modules/eslint-plugin-import
npm WARN   dev eslint-plugin-import@"^2.29.1" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: @typescript-eslint/eslint-plugin@7.4.0
npm WARN Found: eslint@9.2.0
npm WARN node_modules/eslint
npm WARN   dev eslint@"^9.2.0" from the root project
npm WARN   5 more (@eslint-community/eslint-utils, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN node_modules/@typescript-eslint/eslint-plugin
npm WARN   peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.1.0
npm WARN   node_modules/eslint-plugin-unused-imports
npm WARN
npm WARN Conflicting peer dependency: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN   node_modules/@typescript-eslint/eslint-plugin
npm WARN     peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.1.0
npm WARN     node_modules/eslint-plugin-unused-imports
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: @typescript-eslint/parser@7.4.0
npm WARN Found: eslint@9.2.0
npm WARN node_modules/eslint
npm WARN   dev eslint@"^9.2.0" from the root project
npm WARN   5 more (@eslint-community/eslint-utils, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/parser@7.4.0
npm WARN node_modules/@typescript-eslint/parser
npm WARN   peer @typescript-eslint/parser@"^7.0.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN   node_modules/@typescript-eslint/eslint-plugin
npm WARN
npm WARN Conflicting peer dependency: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^8.56.0" from @typescript-eslint/parser@7.4.0
npm WARN   node_modules/@typescript-eslint/parser
npm WARN     peer @typescript-eslint/parser@"^7.0.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN     node_modules/@typescript-eslint/eslint-plugin
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: eslint-plugin-react-hooks@4.6.0
npm ERR! Found: eslint@9.2.0
npm ERR! node_modules/eslint
npm ERR!   dev eslint@"^9.2.0" from the root project
npm ERR!   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm ERR!   node_modules/@eslint-community/eslint-utils
npm ERR!     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.4.0
npm ERR!     node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils
npm ERR!       @typescript-eslint/utils@"7.4.0" from @typescript-eslint/eslint-plugin@7.4.0
npm ERR!       node_modules/@typescript-eslint/eslint-plugin
npm ERR!         peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.1.0
npm ERR!         node_modules/eslint-plugin-unused-imports
npm ERR!       1 more (@typescript-eslint/type-utils)
npm ERR!     @eslint-community/eslint-utils@"^4.2.0" from eslint@9.0.0
npm ERR!     2 more (@typescript-eslint/utils, eslint)
npm ERR!   4 more (eslint-config-prettier, eslint-config-turbo, ...)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer eslint@"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" from eslint-plugin-react-hooks@4.6.0
npm ERR! node_modules/eslint-plugin-react-hooks
npm ERR!
npm ERR! Conflicting peer dependency: eslint@8.57.0
npm ERR! node_modules/eslint
npm ERR!   peer eslint@"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" from eslint-plugin-react-hooks@4.6.0
npm ERR!   node_modules/eslint-plugin-react-hooks
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

対応:eslintの入れ直し

$ npm uninstall eslint
npm WARN cleanup Failed to remove some directories [
npm WARN cleanup   [
npm WARN cleanup     'kartagraph-monorepo\\node_modules\\.turbo-windows-64-wzwOE5fA',
npm WARN cleanup     [Error: EPERM: operation not permitted, unlink 'D:\projects\kartagraph-monorepo\node_modules\.turbo-windows-64-wzwOE5fA\bin\turbo.exe'] {
npm WARN cleanup       errno: -4048,
npm WARN cleanup       code: 'EPERM',
npm WARN cleanup       syscall: 'unlink',
npm WARN cleanup       path: 'kartagraph-monorepo\\node_modules\\.turbo-windows-64-wzwOE5fA\\bin\\turbo.exe'
npm WARN cleanup     }
npm WARN cleanup   ]
npm WARN cleanup ]

added 7 packages, removed 28 packages, changed 128 packages, and audited 1589 packages in 1m

338 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

WARNは出るものの、エラーにはならなくなった。

$ npm i -D eslint@latest
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.8.0
npm WARN node_modules/@typescript-eslint/eslint-plugin
npm WARN   peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.2.0
npm WARN   node_modules/eslint-plugin-unused-imports
npm WARN   1 more (typescript-eslint)
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/parser@7.8.0
npm WARN node_modules/@typescript-eslint/parser
npm WARN   peer @typescript-eslint/parser@"^7.0.0" from @typescript-eslint/eslint-plugin@7.8.0
npm WARN   node_modules/@typescript-eslint/eslint-plugin
npm WARN   1 more (typescript-eslint)
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" from eslint-plugin-import@2.29.1
npm WARN node_modules/eslint-plugin-import
npm WARN   dev eslint-plugin-import@"^2.29.1" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" from eslint-plugin-react-hooks@4.6.2
npm WARN node_modules/eslint-plugin-react-hooks
npm WARN   dev eslint-plugin-react-hooks@"^4.6.2" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"8" from eslint-plugin-unused-imports@3.2.0
npm WARN node_modules/eslint-plugin-unused-imports
npm WARN   dev eslint-plugin-unused-imports@"^3.2.0" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from typescript-eslint@7.8.0
npm WARN node_modules/typescript-eslint
npm WARN   dev typescript-eslint@"^7.8.0" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency

added 6 packages, removed 9 packages, changed 5 packages, and audited 1590 packages in 2s

339 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

ただし、動かなくなった。
依存関係のあるプラグインを再インストールしてみる。

$ npm uninstall eslint-plugin-unused-imports eslint-plugin-import --force
$ npm i -D eslint-plugin-unused-imports eslint-plugin-import --legacy-peer-deps

eslintも再インストールしてみる。

$ npm i -D eslint@latest --legacy-peer-deps

VSCodeを再起動。
無事、lintが効くようになったことを確認した。

(2024.05.19 追記)typescripts-eslintの設定を recommended からstrictに変更した

追加設定でおすすめされていたため。

default.js
export default tseslint.config({
  extends: [
    js.configs.recommended,
-    ...tseslint.configs.recommended,
+    ...tseslint.configs.strict,
+    ...tseslint.configs.stylistic
],

recommended-configurations より

ルール 説明
recommended 追加の設定なしで使用できる、コードの正確性のための推奨ルール。
recommended-type-checked 推奨ルールに加えて、型情報を必要とする追加の推奨ルールを含む。
strict 推奨ルールに加えて、より厳格で意見の分かれるルールを含み、バグの検出も可能。
開発者のかなりの割合が TypeScript に高い熟練度を持っている場合にのみ推奨
strict-type-checked 厳格ルールに加えて、型情報を必要とする追加の厳格ルールを含む。
stylistic 追加の設定なしで使用できるスタイリスティックルール。
stylistic-type-checked スタイリスティックルールに加えて、型情報を必要とする追加のスタイリスティックルールを含む。

下記の記事が違いについてより詳細に解説していた。
サイボウズ フロントエンド typescript-eslint v6 アップデートガイド

参考

ESLintのFlat Config移行でやって良かったこと
ESLint v8.56.0 の reportUnusedDisableDirectives とは何か?
ESLintの設定を視覚化してくれるESLint Config Inspector

findコマンドで-execオプションを使用する時の最後の「{} ;」ってなんだっけ?

サイボウズ フロントエンド typescript-eslint v6 アップデートガイド

11
5
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
11
5