🍵

ESLint Flat Config対応に向けて、Vue3 + TypeScript用のESLintルールを整理する

2023/11/15に公開

はじめに

こんにちは、がんがんです。
2023 年 10 月、ESLint ブログにてFlat config rollout plansという記事が公開されました。
ESLint 公式の発表があったことで 2023 年末〜2024 年始にかけて Flat Config 関連の記事が増えてくると思います。

ただ、ESLint の構成要素を細かく調べていることは珍しく

  • とりあえず recommended 入れておくか
  • とりあえず参考記事の通りにやっておこう(類似: コピペして使う)

というケースが大多数かと思います。その結果、以下の記事のように重複が多く発生します。

https://zenn.dev/kimromi/articles/b7cf98005f3193

また 昨今の Zenn 記事トレンドを鑑みると、Vue3 に関するこの手の移行記事は待っていても多分読めない(or 忘れた頃にやってくる)かなと思ってます。自分が読みたいならば自分で書くしかないってやつですね。


そこで、本記事では Flat Config 対応に向けた構成理解としてeslint-plugin-vueの内部構成を覗いていきます。茶でもしばきながら覗いていってください 🍵

なお、本記事は下記スクラップの延長線上です。

https://zenn.dev/gangannikki/scraps/30ee0996a2db75

eslint-plugin-vue 導入

公式のインストールガイドはこちらです: https://eslint.vuejs.org/user-guide/#installation

terminal
# uses npm
npm i -D eslint-plugin-vue
# uses yarn
yarn add -D eslint-plugin-vue
# uses pnpm
pnpm add -D eslint-plugin-vue

eslint-plugin-vue の構成

公式ドキュメントのConfigurationおよび GitHub のlib/configsを覗いてみます。本記事は Vue3 に関連したものに焦点を当てています。Vue2 については公式ドキュメントを参照ください。以下ドキュメント引用。

  • "plugin:vue/base" ... Settings and rules to enable correct ESLint parsing.
  • Configurations for using Vue.js 3.x.
    • "plugin:vue/vue3-essential" ... base, plus rules to prevent errors or unintended behavior.
    • "plugin:vue/vue3-strongly-recommended" ... Above, plus rules to considerably improve code readability and/or dev experience.
    • "plugin:vue/vue3-recommended" ... Above, plus rules to enforce subjective community defaults to ensure consistency.

base ルールを起点にして essential、strongly-recommended、recommended が用意されています。

configs/base を眺める

base.js の方ではeslint-vue-parserが設定されています。env 設定には browseres6が設定されています。そのため、各プロジェクト内で env.browser を設定するのは重複になります。

https://github.com/vuejs/eslint-plugin-vue/blob/b3129f9f3551f1ac189a0ee84b43561b3d0e4cc2/lib/configs/base.js

続いて vue3-recommended を眺めます。

https://github.com/vuejs/eslint-plugin-vue/blob/b3129f9f3551f1ac189a0ee84b43561b3d0e4cc2/lib/configs/vue3-recommended.js

extends の箇所を見るとextends: require.resolve('./vue3-strongly-recommended')が定義されています。

公式ドキュメントの説明にあった通り、vue3-recommendedvue3-strongly-recommendedを継承した内容になっています。そのため、以下のような方程式が成り立ちます。

vue3-recomended = vue3-recomended固有ルール + vue3-strongly-recomended
                = vue3-recomendend固有ルール + vue3-strongly-recomended固有ルール + vue3-essential
                = vue3-recomendend固有ルール + vue3-strongly-recomended固有ルール + vue3-essential固有ルール + base

Flat Config 化してみる

実験として eslint-plugin-vue を用いた eslint.config.js を書いてみます。以下のような環境を想定しています。

  • eslint:recomendedplugin:@typescript-eslint/recommendedeslint-config-prettierを利用していた
  • Vue3 環境を利用し'plugin:vue/vue3-recommended'を利用していた
  • その他のプラグインは利用していない(大体のケースでは該当しない想定だが最小構成のためです)

compat.extends()で eslint-plugin-vue を利用する

Flat Config 未サポートの場合は@eslint/eslintrc.FlatCompatを利用します。

eslint.config.js
// @ts-check
import { FlatCompat } from '@eslint/eslintrc';
import eslintConfig from '@eslint/js';
import tsEslintPlugin from '@typescript-eslint/eslint-plugin';
import tsEslintParser from '@typescript-eslint/parser';
import eslintConfigPrettier from 'eslint-config-prettier';
import { fileURLToPath } from 'node:url';
import { dirname } from 'pathe';
// NOTE: unjs/patheを利用してますが import { dirname } from 'node:path'でも同様です

const eslintrc = new FlatCompat({
  baseDirectory: dirname(fileURLToPath(import.meta.url))
});

/**
 * ESLint Config for TypeScript
 * @type {import('eslint').Linter.FlatConfig}
 */
const tsEslintConfig = {
  plugins: {
    '@typescript-eslint': tsEslintPlugin,
  },
  files: ['**/*.ts', '**/*.tsx', '**/*.vue'],
  languageOptions: {
    parser: tsEslintParser,
    parserOptions: {
      project: true,
      extraFileExtensions: ['.vue'],
    },
  },
  rules: {
    ...tsEslintPlugin.configs['eslint-recommended'].overrides[0].rules,
    '@typescript-eslint/consistent-type-imports': 'error',
    '@typescript-eslint/no-import-type-side-effects': 'error',
  },
};

/**
 * ESLint Config
 * @type {import('eslint').Linter.FlatConfig[]}
 */
export default [
  {
    ignores: ['**/dist/**/*','**/node_modules/**/*'],
  },
  eslintConfig.configs.recommended,
  tsEsLintConfig,
  ...eslintrc.extends('plugin:vue/vue3-recommended'),
  eslintConfigPrettier,
]

Flat Config 対応後に eslint-plugin-vue を利用する

eslint-plugin-vue の GitHub を見るとSupport for "Flat Configがクローズされていません。
そのため、完全に Flat Config 対応が完了したわけではなさそうですね。

Flat Config 対応後は以下のような構成になるかと思います(以下、上記との差分のみ表示)。

eslint.config.js
- import { FlatCompat } from '@eslint/eslintrc';
+ import vueEslintPlugin from 'eslint-plugin-vue';
+ // import名は任意でよい

export default [
  // other config
  tsEsLintConfig,
- ...eslintrc.extends('plugin:vue/vue3-recommended'),
+ vueEslintPlugin.configs['vue3-recommended']
]

個人的な参考資料: 各プロダクトに Flat Config を対応する時の参考資料は?

.eslintrc.{js,yml,json}からeslint.config.jsへの移行対応は参考資料がまだまだ多くはありません。個人的に参考になった資料はNicholas C. Zakas氏が eslint-plugin-vue や typescript-eslint に対して出されていた Pull Request です。勉強になることが多かったです。

その他の Pull Request や対応については ESLint 公式のイシューにまとめられています。

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

個人的な疑問: Flat Config で eslint-plugin-vue を利用する際、vue-eslint-parser のインストールは必要になるのか

eslint-plugin-vue の ESLint Flat Config について個人的な疑問点です。

従来の extends であればインストールが不要だったかと思いますが、Flat Config 対応後は各プロジェクトごとに必要になるのか。
おそらく公式ドキュメントにて明示があると思いますのでお茶飲みながら待機しておきます 🍵

おわりに

2023.10 に行われたVue Fes Japan 2023にて eslint-plugin-vue@v10 についての案内がありました。

https://ota-meshi.github.io/vue-fes-japan-2023-slide/

eslint-plugin-vue の今後の発展にワクワクしますし、個人的に Nuxt サポートが楽しみです 🎉
これからも貢献できる形でコミュニティに貢献していきたいですね。

Vue・Nuxt 情報が集まる広場 / Plaza for Vue・Nuxt.

Discussion