使用 Codemod 自动化 ESLint 迁移

ESLint 和 Codemod 正在合作提供用于 ESLint 迁移的官方 codemod。

我们很高兴地宣布 ESLint 与 Codemod 建立合作伙伴关系,以为 ESLint 用户创建更好的迁移体验,首先从 ESLint v8 到 v9 和 v9 到 v10 的迁移开始。所有官方 ESLint codemod 都位于 eslint/codemodsCodemod Registry 上。鼓励社区成员针对缺失的 codemod 提出问题或通过拉取请求贡献新的 codemod。一旦维护者审核并合并,codemod 将通过 GitHub Actions 自动发布到 Codemod Registry。

🌐 We are excited to announce a partnership between ESLint and Codemod to create a better migration experience for ESLint users, starting with the ESLint v8 to v9 and v9 to v10 migrations. All official ESLint codemods live in eslint/codemods and on the Codemod Registry. Community members are encouraged to open issues for missing codemods or contribute new ones through pull requests. Once reviewed and merged by maintainers, codemods are automatically published to the Codemod Registry through GitHub Actions.

什么是 Codemod?

🌐 What is Codemod?

Codemod 是一个开源平台,用于构建、共享和大规模运行自动化代码迁移。它是 OpenJS 基金会 的合作伙伴,其工具已被 React、Node.js、Express、React Router、Nuxt.js、pnpm、Webpack、MSW、i18next 等项目采用。

🌐 Codemod is an open source platform for building, sharing, and running automated code migrations at scale. It is an OpenJS Foundation partner, and its tooling has been adopted by projects such as React, Node.js, Express, React Router, Nuxt.js, pnpm, Webpack, MSW, i18next, and more.

其平台包括 JSSG(JS ast-grep)、一个 codemod 运行时和工作流引擎,支持多步骤转换,并将确定性的、具有编译器意识的转换与人工智能驱动的步骤结合起来,以提供可靠性、效率和灵活性的最佳平衡。Codemod CLI 和引擎的源代码可在 GitHub 上获取。

🌐 Its platform includes JSSG (JS ast-grep), a codemod runtime and workflow engine that supports multi-step transformations and combines deterministic, compiler-aware transformations with AI-powered steps to deliver the right balance of reliability, efficiency, and flexibility. The source code for the Codemod CLI and engine is available on GitHub.

Codemod 的主要特点包括:

🌐 Key features of Codemod include:

  • 工作区范围的语义分析
  • 跨文件重构
  • 多语言支持
  • 仓库级性能
  • 一个简单、对代理友好的 API
  • 通过 MCP 内置 AST 检查
  • 安全沙箱执行
  • 指标和代码库挖掘
  • 对多文件转换的本地支持

查看 Codemod 文档 以了解更多关于 JSSG(JS ast-grep)、Codemod 的开源工具包用于构建 codemod 以及探索其功能的信息。

🌐 Check out the Codemod docs to learn more about JSSG (JS ast-grep), Codemod’s open source toolkit for building codemods, and explore its features.

ESLint 从 v8 迁移到 v9

🌐 ESLint v8 to v9 migration

对于从 v8 到 v9 的迁移,我们发布了两个代码转化工具:一个帮助升级 ESLint 配置,另一个用于自定义规则。

🌐 For v8 to v9 migration, we’ve released two codemods: one to help upgrade ESLint config, and another for custom rules.

使用 @eslint/v8-to-v9-config 迁移配置

🌐 Migrating configuration with @eslint/v8-to-v9-config

npx codemod @eslint/v8-to-v9-config

与原始的 ESLint 配置迁移器 不同,这个代码修改工具作为工作区迁移运行。它可以:

🌐 Unlike the original ESLint Configuration Migrator, this codemod runs as a workspace migration. It can:

  • package.json 中提取 eslintConfig 并生成 eslint.config.mjs
  • 清理源文件中重复的 /* eslint */ 注释和无效的 /* exported */ 注释
  • 从内联注释中移除已弃用的 require-jsdocvalid-jsdoc 规则引用
  • 使用 jsdoc({ config: "flat/recommended", ... }) 将那些 JSDoc 规则迁移到 eslint-plugin-jsdoc
  • 当自定义设置需要审核时,请添加 // TODO: Migrate settings manually 评论
  • 处理多个 ESLint v9 规则选项更改,包括 no-unused-varsno-useless-computed-keyno-sequencesno-constructor-returncamelcaseno-restricted-imports
  • 使用 globals 包将 env 转换为 languageOptions.globals
  • excludedFiles 映射到每个配置 ignores
  • noInlineConfigreportUnusedDisableDirectives 移动到 linterOptions
  • 导入解析器包和插件
  • 使用 @eslint/config-helpers 中的 defineConfigglobalIgnores
  • 合并来自 .eslintignore.gitignore 的忽略模式

对于 JavaScript 配置文件,codemod 是从 AST 工作的,并且可以解析简单的绑定,例如 const 值、标识符和展开语法。更高级的逻辑,例如函数、条件语句和动态的 require() 调用,仍然需要人工检查。该工作流程还支持如 --targeteslintConfigCustomNamecodeFormattingCommandEnabled 之类的选项,并在运行后提示你安装所需的包。

🌐 For JavaScript config files, the codemod works from the AST and can resolve simple bindings such as const values, identifiers, and spreads. More advanced logic, such as functions, conditionals, and dynamic require() calls, still needs manual review. The workflow also supports options such as --target, eslintConfigCustomName, and codeFormattingCommandEnabled, and prompts you to install required packages after it runs.

codemod 不会迁移 --ext CLI 的使用,因此你仍然需要为之前在命令行中传递的文件扩展名创建配置条目。更多信息请参阅 @eslint/v8-to-v9-config 的注册页面配置迁移指南

🌐 The codemod does not migrate --ext CLI usage, so you still need to create a config entry for the file extensions you previously passed on the command line. Learn more on @eslint/v8-to-v9-config’s registry page and in the configuration migration guide.

使用 @eslint/v8-to-v9-custom-rules 迁移自定义规则

🌐 Migrating custom rules with @eslint/v8-to-v9-custom-rules

npx codemod @eslint/v8-to-v9-custom-rules

重要提示: 仅在包含 ESLint 规则文件的目录中运行此 codemod。它可能会错误地转换其他导出函数的 JavaScript 文件。

该 codemod 支持 CommonJS(module.exports = function (context) { ... })、ES 模块(export default function (context) { ... })、间接导出(function rule() {}module.exports = rule)、高阶封装器如 wrapRule(function (context) { ... }),以及使用 @typescript-eslint/utils RuleCreator 创建的规则。

🌐 The codemod supports CommonJS (module.exports = function (context) { ... }), ES Modules (export default function (context) { ... }), indirect exports (function rule() {} and module.exports = rule), higher-order wrappers such as wrapRule(function (context) { ... }), and rules created with @typescript-eslint/utils RuleCreator.

它执行从 v8 到 v9 的自定义 ESLint 规则的全面迁移,包括:

🌐 It performs a comprehensive migration of custom ESLint rules from v8 to v9, including:

  • 已移除 context 方法 — 将调用迁移到 sourceCode 等效方法(例如,context.getSource()sourceCode.getText()),包括那些以不同签名移动的方法,如 getScope()getAncestors()getDeclaredVariables()markVariableAsUsed()
  • context 方法变为属性 — 将 getSourceCode()getFilename()getPhysicalFilename()getCwd() 迁移到它们对应的属性,并提供兼容性回退
  • 已移除 context.getComments() — 将节点特定调用转换为 getCommentsBefore / getCommentsInside / getCommentsAfter(node)
  • 已移除 CodePath#currentSegments — 添加代码路径追踪逻辑(请验证结果是否符合你的规则需求)
  • 函数式规则不再受支持 — 转换为带有 metacreate 的对象格式

这个 codemod 还会将 module.exports.schema 移动到 meta,将老式的 context.report(node, message) 调用转换为对象格式,检测可修复的规则,并将 fixable: "code" 添加到 meta

🌐 The codemod also moves module.exports.schema into meta, converts old-style context.report(node, message) calls to object format, detects fixable rules, and adds fixable: "code" to meta.

涵盖 context.parserOptionscontext.parserPath,因为这些属性直到 ESLint v10.0.0 才会被移除。建议使用 context.languageOptions(以及在需要解析器时使用 context.languageOptions.parser)代替。

🌐 It does not cover context.parserOptions and context.parserPath, because those properties are not removed until ESLint v10.0.0. Prefer context.languageOptions (and context.languageOptions.parser when you need the parser) instead.

并非所有的更改都可以完全自动化。在运行 codemod 之后:

🌐 Not every change can be fully automated. After running the codemod:

  1. 检查 TODO 注释。 在你迁移的文件中搜索 TODO。如果某条规则使用了 context.options,codemod 可能会留下一个占位符,比如 schema: [] // TODO: Define schema - this rule uses context.options,你需要将其替换为有效的 JSON schema。
  2. 审核评论方法更改。 getCommentsBefore()getCommentsInside()getCommentsAfter() 需要一个 node 参数,而无参数的 context.getComments() 调用应使用 sourceCode.getAllComments()
  3. 检查跳过的高阶封装器。 如果一个封装器将配置作为第二个参数传递(例如,wrapRule(rule, config)),请确认是否需要任何手动迁移。
  4. **通过运行规则测试套件(例如,npm test)**来测试你的自定义规则。

@eslint/v8-to-v9-custom-rules的注册页面了解更多信息。有关完整的 API 更改列表以及如何手动采用它们,请参阅ESLint v9 迁移指南v9 自定义规则博客文章

🌐 Learn more on @eslint/v8-to-v9-custom-rules’s registry page. For the full list of API changes and how to adopt them manually, see the ESLint v9 migration guide and the blog post for v9 custom rules.

ESLint 从 v9 迁移到 v10

🌐 ESLint v9 to v10 migration

使用以下 codemod 将你的 ESLint 项目从 v9 升级到 v10:

🌐 Upgrade your ESLint project from v9 to v10 with the following codemod:

npx codemod @eslint/v9-to-v10

此配方包含四个独立的代码修改,每个代码修改也可以独立运行:

🌐 This recipe includes four individual codemods, each of which can also be run independently:

  • @eslint/v9-to-v10-config:移除旧的环境变量和命令行选项
  • @eslint/v9-to-v10-custom-rules:替换已移除的上下文和源代码方法
  • @eslint/v9-to-v10-ruletester:清理 RuleTester 测试用例
  • @eslint/v9-to-v10-linter-api:修复 Linter/ESLint API 使用

查看 Codemod Registry 以了解有关此方案及其 codemod 的更多信息。有关 v10 中的新功能以及如何采用新功能的详细信息,请参考 官方 ESLint 升级指南

🌐 Check out Codemod Registry to learn more about this recipe and its codemods. For more details about what’s new in v10 and how to adopt the new features, refer to the official ESLint upgrade guide.

结论

🌐 Conclusion

跨主要 ESLint 版本的升级通常意味着需要手动仔细地翻译配置、自定义规则和相关 API。通过这一合作,官方 Codemod 工作流程为你提供了从 v8 到 v9 和 v9 到 v10 迁移的更快速起点,同时仍为复杂项目所需的手动审核步骤保留了空间。

🌐 Upgrading across major ESLint versions has often meant carefully translating configs, custom rules, and related APIs by hand. With this partnership, official Codemod workflows give you a faster starting point for the v8 to v9 and v9 to v10 migrations, while still leaving room for the manual review steps that complex projects need.

你可以通过 Codemod Registry 今日尝试 codemods,并在 eslint/codemods 找到源代码。如果遇到空缺,可以提出 issue 或贡献新的 codemod。有关迁移本身的问题,请参阅 v9v10 升级指南,或访问 Discord 与团队交流。

🌐 You can try the codemods today through the Codemod Registry, and find the source in eslint/codemods. If you run into a gap, open an issue or contribute a new codemod. For questions about the migrations themselves, see the v9 and v10 upgrade guides, or stop by Discord to talk with the team.

最新的 ESLint 新闻、案例研究、教程和资源。

ESLint v10.8.0 发布
2 min read

ESLint v10.8.0 发布

我们刚刚发布了 ESLint v10.8.0,这是 ESLint 的一次小版本升级。此版本添加了一些新功能,并修复了上一版本中发现的几个错误。

ESLint v9.39.5 发布
1 min read

ESLint v9.39.5 发布

我们刚刚发布了 ESLint v9.39.5,这是 ESLint 的一个补丁版本升级。本次发布修复了上一版本中发现的几个错误。

ESLint v10.7.0 发布
2 min read

ESLint v10.7.0 发布

我们刚刚发布了 ESLint v10.7.0,这是 ESLint 的一次小版本升级。此版本添加了一些新功能,并修复了上一版本中发现的几个错误。