GMOメイクショップ コアグループ エンジニアの森です。
我々のプロジェクトではメンバー間でのコードの一貫性を保つためにESLintを導入しています。
このESLintですがバージョンアップに伴い、設定ファイルの記法をFlat Configという形式にする必要が出てきました。今回はこの移行手順について書いていきます。
ESLint・Flat Configについて
ESLintとはJavaScriptやTypeScriptなどのコードの静的解析ツールです。コードスタイル等のルールを作成し、従っているかどうかを検証することができます。
従来の設定ファイルはeslintrcの形式で書かれていましたが、ESLintのバージョンアップに伴いFlat configがデフォルトとなり、2024年末から2025年初頭にかけてリリース予定のv10.0.0移行はeslintrcが完全に廃止される見込みです。
そのため2024年中にはeslintのFlat Config化が必要となります。
eslint.org
移行手順
ESLint設定の各プロパティの移行方法について、修正の前後を比較しながら説明します。
ここで紹介するコードは、実際に使用しているファイルから一部修正・省略したものです。
1.plugins
Pluginsプロパティは、rulesで使用するパッケージを登録します。 eslintrcではパッケージごと決められた命名で直接pluginsに追加していましたが、 Flat Configでは任意の名前でimportしてから追加する必要があります。
plugins: ['vue', 'import', 'unused-imports'],
import vue from 'eslint-plugin-vue' import eslintPluginImport from 'eslint-plugin-import' import eslintPluginUnusedImports from 'eslint-plugin-unused-imports' plugins: { vue, eslintPluginImport, eslintPluginUnusedImports, },
2.extends
extendsプロパティに追加すると、パッケージの共有設定を適用することができます。 Flat Configではextendsプロパティがなくなっているため、export defaultに直接追加します。
パッケージがFlat Configに対応していない場合
Flat Configに対応しているパッケージの場合はimportを直接書くことで移行できますが、未対応のパッケージには、FlatCompat()
を使う必要があります。
eslint.org
パッケージがFlat Configに対応しているかはドキュメントやソースを確認する必要があります。
例えばeslint-plugin-vue
の場合、ドキュメントにFlat Configでの書き方が記載されています。
eslint.vuejs.org
extends: [ 'eslint:recommended', 'plugin:vue/vue3-recommended', 'plugin:vue-scoped-css/vue3-recommended', 'plugin:@typescript-eslint/eslint-recommended', 'eslint-config-prettier', 'plugin:vuetify/base', ],
const compat = new FlatCompat({ baseDirectory: dirname(fileURLToPath(import.meta.url)), }) export default [ eslintJs.configs.recommended, ...vue.configs['flat/recommended'], ...eslintPluginVueScopedCSS.configs['flat/recommended'], ...compat.extends('plugin:@typescript-eslint/eslint-recommended'), eslintConfigPrettier, ...compat.extends('plugin:vuetify/base'), /// 省略 //// ]
3.env・parser
envはグローバル変数を設定するためのオプションでしたが、Flat Configではglobalsに置き換わり、
parserと一緒にlanguageOptionsプロパティに定義します。
なお
globals
は事前にyarn add globals
コマンドでインストールする必要があります。
vue/setup-compiler-macros
なお移行したタイミングで'vue/setup-compiler-macros': true
がなくなっていますが、これはvue-eslint-parser
のv9.0.0以降を使用している場合は不要になるため削除しました。
eslint.vuejs.org
env: { 'es6': true, 'node': true, 'mocha': true, 'es2022': true, 'vue/setup-compiler-macros': true, }, parserOptions: { parser: '@typescript-eslint/parser', sourceType: 'module', ecmaVersion: 'latest', ecmaFeatures: { jsx: true, modules: true, }, },
import vueEslintParser from 'vue-eslint-parser' /// 省略 //// languageOptions: { globals: { ...globals.node, ...globals.es2021, }, parser: vueEslintParser, parserOptions: { ecmaVersion: 'latest', }, },
4.rules
rulesはeslintrcもFlat Configも書き方は同じです。
ただしplugins
のimport名が変わっている場合は、それに合わせて修正が必要です。
import/order
→ eslintPluginImport/order
rules: { 'vue/no-deprecated-html-element-is': 2, 'no-multi-spaces': 2, 'import/order': [ 'error', /// 省略 //// ], },
rules: { 'vue/no-deprecated-html-element-is': 2, 'no-multi-spaces': 2, 'eslintPluginImport/order': [ 'error', /// 省略 //// ], },
5.overrides
overridesは対象のファイルに対して、別のルールを適用できるプロパティです。
Flat Configでは廃止されており、通常ルールと並べて配置することができます。
commonConfig
、exceptionConfig
のようにルール毎に定義すると見やすくわかりやすいです。
overrides: [ { files: [ 'Exception.vue', 'exception.ts', ], rules: { 'no-restricted-imports': ['off'], }, }, ],
const exceptionConfig = { files: [ 'Exception.vue', 'exception.ts', ], rules: { 'no-restricted-imports': ['off'], }, } export default [ /// 省略 //// commonConfig, exceptionConfig, ]
6.ファイル全体
最終的に移行前後でファイル全体は以下のようになりました。
移行前 eslintrc
module.exports = { plugins: ['vue', 'import', 'unused-imports'], extends: [ 'eslint:recommended', 'plugin:vue/vue3-recommended', 'plugin:vue-scoped-css/vue3-recommended', 'plugin:@typescript-eslint/eslint-recommended', 'eslint-config-prettier', 'plugin:vuetify/base', ], env: { 'es6': true, 'node': true, 'mocha': true, 'es2022': true, 'vue/setup-compiler-macros': true, }, parserOptions: { parser: '@typescript-eslint/parser', sourceType: 'module', ecmaVersion: 'latest', ecmaFeatures: { jsx: true, modules: true, }, }, rules: { 'vue/no-deprecated-html-element-is': 2, 'no-multi-spaces': 2, 'import/order': [ 'error', /// 省略 //// ], }, overrides: [ { files: [ 'Exception.vue', 'exception.ts', ], rules: { 'no-restricted-imports': ['off'], }, }, ], }
移行後 Flat Config
import { fileURLToPath } from 'url' import { FlatCompat } from '@eslint/eslintrc' import eslintJs from '@eslint/js' import eslintConfigPrettier from 'eslint-config-prettier' import eslintPluginImport from 'eslint-plugin-import' import eslintPluginUnusedImports from 'eslint-plugin-unused-imports' import vue from 'eslint-plugin-vue' import eslintPluginVueScopedCSS from 'eslint-plugin-vue-scoped-css' import globals from 'globals' import { dirname } from 'pathe' import vueEslintParser from 'vue-eslint-parser' const compat = new FlatCompat({ baseDirectory: dirname(fileURLToPath(import.meta.url)), }) const commonConfig = { languageOptions: { globals: { ...globals.node, ...globals.es2021, }, parser: vueEslintParser, parserOptions: { ecmaVersion: 'latest', }, }, plugins: { vue, eslintPluginImport, eslintPluginUnusedImports, }, rules: { 'vue/no-deprecated-html-element-is': 2, 'no-multi-spaces': 2, 'eslintPluginImport/order': [ 'error', /// 省略 //// ], }, } const exceptionConfig = { files: [ 'Exception.vue', 'exception.ts', ], rules: { 'no-restricted-imports': ['off'], }, } export default [ eslintJs.configs.recommended, ...vue.configs['flat/recommended'], ...eslintPluginVueScopedCSS.configs['flat/recommended'], ...compat.extends('plugin:@typescript-eslint/eslint-recommended'), eslintConfigPrettier, ...compat.extends('plugin:vuetify/base'), commonConfig, exceptionConfig, ]
まとめ
eslintのFlat Config移行について書きましたが、これには既に先駆者が多くおり、私もたくさんの記事を参考にさせてもらいました。
環境によってはこの記事がマッチしないこともあると思いますので、他の記事と合わせて移行の参考にしていただければ嬉しいです。
今回のeslintに限らずツールやライブラリのバージョンアップには中々頭を悩ませることも多いので、余裕を持って対応しておきたいですね。
参考記事
- Configuration Migration Guide
- ESLint を eslintrc から Flat Config に移行する、ハマりポイントを添えて。
- ESLintのeslintrcをFlat Configに移行してみた