手记

我在从旧版本迁移到ESLint 9时遇到的问题及如何经历这些坎坷

作为一名软件工程师,你需要维护和更新你的基础设施,确保它始终保持最新。

绘制一个工程电脑控制台,配置档案显示在终端上,采用80年代合成波风格的

我不觉得自己是程序员,更像是质量保证工程师。所以我用JavaScript的一些工具来帮助我做自动化测试。像ESLintPrettier这样的工具可以帮助编写整洁的代码,设置起来也很容易。这样可以在不深入了解细节的情况下获得最大效益。然而,当我需要从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)。

0人推荐
随时随地看视频
慕课网APP