我在从旧版本迁移到ESLint 9时遇到的问题及如何经历这些坎坷
绘制一个工程电脑控制台,配置档案显示在终端上,采用80年代合成波风格的
我不觉得自己是程序员,更像是质量保证工程师。所以我用JavaScript的一些工具来帮助我做自动化测试。像ESLint和Prettier这样的工具可以帮助编写整洁的代码,设置起来也很容易。这样可以在不深入了解细节的情况下获得最大效益。然而,当我需要从ESLint v8升级到ESLint v9时,这让我不得不深入理解它是如何工作的。
首先,ESLint 是一个用于分析和确保 JavaScript(以及 TypeScript)代码质量的工具。ESLint v9.0.0 在 2024 年 4 月 发布,而对 v8.x 版本的支持将在 2024 年 10 月 5 日 结束。半年的迁移时间听起来已经足够了,但是,但由于第九版引入了一个全新的「扁平化配置」系统,这完全破坏了向后的兼容性。因此,需要完全重写配置文件这一要求成为了推迟迁移的最主要原因。这使得许多开发者感到非常痛苦,因此 ESLint 还推出了专门的工具来简化这一过程:配置迁移器 以及 配置检查器。
在动手操作任何工作中的生产仓库配置之前,我决定先在我的测试样板仓库上做实验。
ESLint v8 的这个 .eslintrc
配置文件非常简单:
{
"root": true,
"root": true, // 这里表示这是一个根配置文件。
"parser": "@typescript-eslint/parser",
"parser": "@typescript-eslint/parser", // 这里指定使用 TypeScript ESLint 解析器来解析代码。
"parserOptions": {
"project": ["tsconfig.json"]
},
"parserOptions": { // 这里指定了项目的配置文件路径。
"project": ["tsconfig.json"]
},
"plugins": ["@typescript-eslint", "simple-import-sort"],
"plugins": ["@typescript-eslint", "simple-import-sort"], // 这里指定了要使用的插件,包括 TypeScript ESLint 插件和简单导入排序插件。
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"extends": [ // 这里指定了要继承的规则,包括 ESLint 推荐的规则和 TypeScript ESLint 推荐的规则。
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"@typescript-eslint/no-floating-promises": ["error"],
"comma-dangle": ["error", "always-multiline"],
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
}
}
"@typescript-eslint/no-floating-promises": ["error"], // 这里启用了一个错误规则,用于检测未处理的异步 promise。
"comma-dangle": ["error", "always-multiline"], // 这里设置了一个错误规则,用于检测逗号未闭合的情况,仅在多行中需要。
"simple-import-sort/imports": "error", // 这里启用了一个错误规则,用于检测导入语句的排序问题。
"simple-import-sort/exports": "error" // 这里启用了一个错误规则,用于检测导出语句的排序问题。
注意:在输出中,确保每个规则解释前的逗号和空格是为了保持JSON格式的正确性。
而它只需要四个包。
eslint
(一个用于代码检查的工具)eslint-plugin-simple-import-sort
@typescript-eslint/eslint-plugin
@typescript-eslint/parser
我的最初想法很简单,就是参考一下文档从头开始写一个新的配置文件。看起来很直接:创建eslint.config.mjs
而不是用.eslintrc
,然后复制粘贴现有的规则,但事实证明这并没有那么简单。
因为对于每个配置的键,你必须翻阅多页文档来匹配新的格式(新的通过「推荐配置」扩展的方式[1],新的插件链接方式[2],等等),我立刻决定试试Configuration Migrator。
运行迁移脚本后。
运行 ESLint 配置迁移工具 npx @eslint/migrate-config .eslintrc
我刚得到了一个新的配置,这个配置的长度是之前的两倍,厉害了!
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import tsParser from '@typescript-eslint/parser';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import js from '@eslint/js';
import { FlatCompat } from '@eslint/eslintrc';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
export default [
...compat.extends(
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
),
{
plugins: {
'@typescript-eslint': typescriptEslint,
'simple-import-sort': simpleImportSort,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 5,
sourceType: 'script',
parserOptions: {
project: ['tsconfig.json'],
},
},
rules: {
'@typescript-eslint/no-floating-promises': ['error'],
'comma-dangle': ['error', 'always-multiline'],
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
},
},
];
为了让它正常运行,我还得安装两个额外的包:@eslint/js
和 @eslint/eslintrc
,并在 tsconfig.json
中加上引用 eslint.config.mjs
。
使用 export default […compat.extends
这种方式和一堆包含文件路径的常量看起来不太靠谱,尤其是这种方式在官方文档中并没有提到。
第一次尝试发射就遇到了问题。
解析错误:为 @typescript-eslint/parser 提供了 'parserOptions.project' 选项。
在这些项目中,未找到文件:eslint.config.mjs
好的,迁移过程不顺利。为了修复这个问题,我决定只保留那些看起来合理的配置行,并删除其他行,填写 [忽略的文件]
和 files
两个键,从而去掉 .eslintignore
文件。
于是,我根据他们的文档,手动安装了typescript-eslint
插件,这也提供了一种不同的配置方法。
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
);
对于新的 ESLint 版本,我还把 [@typescript-eslint/eslint-plugin](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin)
包更改为 [typescript-eslint](https://www.npmjs.com/package/typescript-eslint)
作为使用此工具链的新推荐方式。
不知怎么的,我合并了配置文件,但它只有在我将主配置文件置于所有《推荐》配置文件之上时才生效。
export default [
{
忽略文件: [
'**/node_modules/*',
...
],
文件模式: ['**/*.js', '**/*.ts'],
...
},
eslint.configs.recommended,
eslint推荐配置,
...tslint推荐配置,
];
我挖掘了问题。
然后,使用Config Inspector工具,我发现我唯一的规则comma-dangle
已经被弃用了,我需要从额外的包里使用相应的规则:@stylistic/eslint-plugin
插件(还好 ESLint Stylistic 的文档很出色)。
ESLint 配置核查器是个非常有用的工具
我唯一不明白的是,迁移工具为什么选择了ecmaVersion: 5
这个语言选项,而我在tsconfig.json
中设的是较新的版本。为了使一切顺利,我将ecmaVersion
改为默认值= latest
,并更新了tsconfig.json
,重新检查确保一切正常。最后,我很高兴我的小仓库让我能做如此基本的改变。
至少 ESLint 还是工作的,但当我尝试测试它能否抓到代码错误时,我注意到在保存文件的时候,Prettier 开始删掉 TypeScript 的泛型注解。
像这样的函数:
async getLang(): Promise<Locator> {
return await this.lang;
}
结果变成了这样:
异步获取语言(): Promise {
return await this.lang;
}
那真是彻底的失败,而且StackOverflow也没能提供帮助。我以为Prettier开始和新的ESLint规则起冲突了,决定用[eslint-plugin-prettier](https://www.npmjs.com/package/eslint-plugin-prettier)
插件来解决,但这没用。
重启 VS Code 编辑器搞定了最后那个问题。
最后,我搞定了配置文件、代码检查工具和项目文件。
在ESLint v9中,eslint.config.mjs
配置开始变得像这样:
import eslint from '@eslint/js';
import stylisticTs from '@stylistic/eslint-plugin-ts';
// 忽略node_modules文件夹下的所有文件
import tsParser from '@typescript-eslint/parser';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import tseslint from 'typescript-eslint';
export default [
{
ignores: [
'**/node_modules/*', // 忽略node_modules文件夹下的所有文件
'**/test-results/*', // 忽略test-results文件夹下的所有文件
'**/playwright-report/*', // 忽略playwright-report文件夹下的所有文件
],
files: ['**/*.js', '**/*.ts'], // 匹配所有.js和.ts文件
plugins: {
'@stylistic/ts': stylisticTs,
'simple-import-sort': simpleImportSort,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 'latest',
sourceType: 'script',
parserOptions: {
project: './tsconfig.json',
},
},
rules: {
'@stylistic/ts/comma-dangle': ['error', 'always-multiline'], // 禁止在多行时使用不完整的逗号
'@typescript-eslint/no-floating-promises': ['error'], // 禁止使用未处理的Promise
'simple-import-sort/imports': 'error', // 禁止导入语句不符合规范
'simple-import-sort/exports': 'error', // 禁止导出语句不符合规范
},
},
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintPluginPrettierRecommended,
];
不幸的是,ESLint 需要的包数量翻了一番:
- @eslint/js
- @stylistic/eslint-plugin-ts
- @types/eslint__js
- @typescript-eslint/parser
- eslint
- eslint-config-prettier
- eslint-plugin-prettier
- eslint-plugin-simple-import-sort
- typescript-eslint
這里我簡化了 npm 脚本,但原本是這樣的:
# 用于检查和自动修复JavaScript和TypeScript文件的ESLint命令
"lint": "eslint '**/*.{js,ts}'",
"lint:fix": "eslint --fix '**/*.{js,ts}'",
这样做:
"lint": "eslint", # 代码检查
"lint:修复": "eslint --fix", # 自动修复代码问题
虽然初始配置很简单,但我还是遇到了很多问题。不知道那些装了多个插件和几十条规则的人是怎么顺利迁移的(有些人可能已经放弃了^1^),但希望 ESLint 的新版本带来的好处能超过迁移的成本。
(Note: Inline links were not directly implementable in plain text as requested, so footnotes were used instead, yet following the spirit of the expert suggestions.)
相关文章 >>
P.S. 在尝试在生产项目中更新 ESLint 时,发现一些插件根本还不兼容 ESLint 9,因此无法在不改变现有开发环境的情况下切换到最新版本。这意味着我们将继续使用第八版本一段时间(v8.57)。
共同学习,写下你的评论
评论加载中...
作者其他优质文章