WSの小屋

前段时间 ESLint 团队在 Github 上做出了一项重要决定,在未来将要放弃部分规则的维护,并希望通过社区去维护这些工作。于是,antfu 大佬决定通过 ESLint Stylistic 项目来迁移并维护这些工作。

最近我发现,antfu 对他维护的 @antfu/eslint-config 配置也同步做了重大升级,并采用了 ESLint 全新的扁平化配置来重构 eslint-config。关于 ESlint 的扁平化配置我是第一次听说,于是深入的学习了一波。

配置扁平化

在 2013 年 ESLint 首次发布时,配置起来相当简单,但是经过多年的迭代,配置系统变得一团糟(官方说的)。因此,ESLint 团队决定创建一个新的配置系统(flat config)来解决这些问题。这个想法最早在 2022 年就提出了,然而到了 2023 年我才了解到它 o(╥﹏╥)o。

如果你对背景感兴趣,可以查看 《ESLint's new config system》 这篇文章。

新的配置文件

旧的配置系统中支持多种格式的配置文件,比如:

  • .eslintrc
  • .eslintrc.json
  • .eslintrc.js

后文中统称为 eslintrc

在扁平化配置中,使用了全新的配置文件名标准:

  • eslint.config.js

扁平化配置只支持一种配置文件,这样可以减少读取和解析配置文件的时间。如果项目中同时存在两种配置文件,它会首先尝试加载 eslint.config.js文件。如果没有找到,它将再去查找 .eslintrc* 文件。

这是 v8.35.0 版本增加的一个实验性功能。你可以在项目根目录创建 eslint.config.js 文件或将 ESLINT_USE_FLAT_CONFIG 环境变量设置为 true 来开启这项功能。

VSCode 默认情况下是不支持扁平化配置的,我们需要在 .vscode/setting.json 中设置:

hljs 复制代码
{
  "eslint.experimental.useFlatConfig": true
}

支持 ESM 语法

在 eslintrc 中,我们只能编写 CJS 语法。但是如果你使用新的配置文件,你可以选择使用 ESM 或 CJS 两种语法编写配置文件。

与旧的 eslintrc 配置不同,新的配置文件将返回一个配置数组,而不是一个对象。

eslintrc 配置文件写法:

hljs 复制代码
// .eslintrc.js
module.exports = {
 // your config
}

扁平化配置使用 CJS 写法:

hljs 复制代码
// eslint.config.js
module.exports = [
  { // your config },
  { // your config },
]

扁平化配置使用 ESM 写法:

hljs 复制代码
// eslint.config.js
export default [
  { // your config },
  { // your config },
]

使用 ESM 可能要在项目 package.json 文件中指定 "type":"module" 字段

不再需要 overrides

在旧的 eslintrc 中,如果需要对特定文件进行单独配置,需要使用 overrides 字段。例如:

hljs 复制代码
module.exports = {
  overrides: [
     {
       files: ["*.js", "*.mjs"],
       ignorePatterns: ["**/mocks/*.ts"],
       rules: {
         // some rules
       },
     }
  ]
}

而在扁平化配置中,每个配置对象都有可选的  files  和  ignores 字段,用于指定基于最小匹配的 glob模式 来匹配文件。因此,我们不再需要 overrides 字段来进行实现覆盖了。(每个文件就像是单独配置的。)

hljs 复制代码
export default [
  {
    files: ["**/*.js"],
    ignores: ["**/*.test.js"],
  },
  {
    files: ["**/*.ts"],
    ignores: ["**/*.test.ts"],
  }
];

如果您有两个配置对象匹配相同的文件并定义了冲突的规则,有效的配置对象将始终是最后一个,和上文中配置的解析逻辑是相同的。

有了 files 和 ignores 字段,感觉以后 .eslintignore 文件和 eslint --ext .js,.vue 参数基本上不需要了。

移除 extends

在旧的 eslintrc 配置中,extends 字段允许用户导入另一个配置,然后对其进行扩展。假设我们想使用 eslint-config-vue 的配置:

在旧的 eslintrc 配置中:

hljs 复制代码
module.exports = {
  extends: ['vue'],
  rules: {
    "vue/block-order": "off",
    // 添加自己的 `rules` 设置
  }
}

如果使用扁平化配置,我们需要这样做:

hljs 复制代码
import vueConfig from "eslint-config-vue"

export default [
   vueConfig, // <--这里
    {
      files: ["**/*.js", "**/*.cjs"],
      rules: {
        "semi": "error",
        "no-unused-vars": "error"
      }
    },
]

注意:

  • 在旧的 eslintrc 配置中,当使用 extends 导入共享配置时,extends 值是一个字符串,并且不需要手动引入,只需在项目中安装该包即可。
  • 在扁平化配置中,当导入共享配置时,我们需要手动 import 该配置,并将其添加为配置数组中的一项使用。

在扁平化配置中,建议将外部配置首先插入到数组中,以便它成为该文件的配置基础。因为配置的解析顺序是从数组的顶部向下到底部进行的,ESLint 会组合两个 config 对象来创建文件的最终配置,当遇到配置冲突时,后面的配置会覆盖前面的。

新的插件配置

扁平化配置中使用插件和在 eslintrc 中使用非常相似。最大的区别是 eslintrc 使用字符串,而扁平化配置使用对象。这与上面共享配置遵循相同的原则。例如:

hljs 复制代码
import vue from "eslint-plugin-vue";

export default [
   {
      files: ["**/*.vue"],
      plugins: {
        vue
      }
      rules: {
        "vue/block-order": "off",
      }
   }
]

插件支持重命名

在上面的配置中,我们使用插件 eslint-plugin-vue,并使用 vue 变量导入作为 plugins 配置的值。

与 eslintrc 中使用插件不一样的是,扁平化配置中没有严格的插件名称,支持插件重命名。当我们想要覆盖插件内部的规则时,使用 plugins 的键作为命名空间,比如:

hljs 复制代码
import vue from "eslint-plugin-vue";
import ts from "@typescript-eslint/eslint-plugin";

export default [
   {
      files: ["**/*.vue"],
      plugins: {
        newName: vue,
        ts
      }
      rules: {
        "newName/block-order": "off",
      }
   }
]

@antfu/eslint-config 中多处使用了这个特点,使规则看起来更加一致,使用时不需要关心它们来自哪个插件。当你要覆盖规则或内联禁用规则时,需要更新为新前缀:

hljs 复制代码
-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
+// eslint-disable-next-line ts/consistent-type-definitions
type foo = { bar: 2 }

移除 env 选项

在旧的 eslintrc 配置中,为了让 eslint 支持 NodeJS 相关的全局变量,我们需要这么做:

hljs 复制代码
module.exports = {
  env: {
    node: true,
  },
};

但是在扁平化配置中已经不需要了。另外,我们可以在 globals 属性中定义可用的全局变量:

hljs 复制代码
export default [
  {
    files: ["**/*.js"],
    languageOptions: {
      globals: {
        wx: "readonly",
      },
    },
  },
];

除此之外,ESLint 团队建议我们使用一个名为 globals 的包,该包从 ESLint 中提取了所有环境信息:

hljs 复制代码
import globals from "globals";

export default [
    {
        files: ["**/*.js"],
        languageOptions: {
            globals: {
                ...globals.browser,
                myCustomGlobal: "readonly"
            }
        }
    }
];

新的 language option

在扁平化配置中,所有与 JavaScript 相关的配置项移动到一个名为  languageOptions  的新顶级选配置中,主要选项如:

  • ecmaVersion
  • sourceType
  • globals
  • parser
  • parserOptions
hljs 复制代码
export default [
  {
    files: ["**/*.js"],
    languageOptions: {
      ecmaVersion: 2021,
      sourceType: "module",
      globals: {},
      parser: babelParser,
      parserOptions: {
        babelOptions: {},
      },
    },
  },
];

总结

本文主要分享学习 ESLint 新扁平化配置系统的一些总结。新的配置系统使得 ESLint 配置更加简洁和灵活,并提供了更好的可扩展性和可定制化。如果你对此感兴趣,强烈建议阅读官方文档,了解更多新特性和新变化。

原文

[ESLint 新扁平化配置使用指南]( https://juejin.cn/post/7282606413841580091 )

Comments | 0条评论