ESLint v2.0.0 迁移指南:从 0.x/1.x 升级到第二个大版本的完整变更解析 📅 发布时间:2026/9/13 8:06:57 👁 浏览次数: ESLint v2.0.0 迁移指南从 0.x/1.x 升级到第二个大版本的完整变更解析【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslintESLint v2.0.0 是项目历史上第二个大版本major发布它在 0.x 与 1.x 时代的工作方式之上引入了大量破坏性变更包括规则 Schema 不再校验严重级别、ecmaFeatures全面迁移为parserOptions、移除多条旧规则、修正全局作用域分析、SourceCode构造函数开始处理 Unicode BOM以及插件不再自带默认配置等。本文以仓库内官方迁移文档 docs/src/use/migrating-to-2.0.0.md 为主线逐条拆解每项变更的成因、影响范围与具体改法并对照当前仓库源码如 lib/languages/js/source-code/source-code.js、lib/rules/strict.js、conf/globals.js 等验证这些设计在后续版本中的延续形态帮助规则开发者、插件作者与配置维护者在升级时一次到位。重要如果你是从 0.x 直接升级请先以 Migrating to 1.0.0 为起点再阅读本文处理 1.x → 2.0.0 的增量变更。规则 Schema 不再负责校验自身严重级别变更原因在旧版本中由于规则 schema 工作方式上的一个历史遗留怪癖quirk当规则选项足够复杂时规则开发者不得不把规则严重级别0、1、2也纳入规则自己的 schema 中参与校验。这会导致出现如下形式的 schemamodule.exports { type: array, items: [ { enum: [0, 1, 2], }, { enum: [always, never], }, ], minItems: 1, maxItems: 2, };这种做法让规则开发者感到困惑——严重级别是 ESLint 核心机制的一部分本不该由每条规则自己去验证。因此在 v2.0.0 中规则不再需要检查自己的严重级别。迁移改法如果你导出的规则 schema 中包含对严重级别的校验需要做三处修改从 schema 中移除严重级别那一项将minItems从 1 调整为 0将maxItems减去 1。上面示例正确转换后的 schema 为module.exports { type: array, items: [ { enum: [always, never], }, ], minItems: 0, maxItems: 1, };从当前仓库的实现看现代规则普遍采用meta.defaultOptions与meta.schema分离的写法例如 lib/rules/strict.js 中defaultOptions: [safe]与 schema 并列正是延续了 v2.0.0 确立的严重级别与规则选项解耦这一设计原则。移除的规则及其替代方案v2.0.0 废弃了以下规则并创建新规则取而代之。迁移时需更新规则配置以使用新规则同时v2.0.0 会在你使用已被移除的规则时给出警告并提示对应的替代规则以降低升级过程中的意外。已移除规则替代规则no-arrow-condition由 no-confusing-arrow 与 no-constant-condition 组合替代同时开启这两条规则可获得与no-arrow-condition相同的功能no-empty-labelno-labels配合{allowLoop: true, allowSwitch: true}选项space-after-keywordskeyword-spacingspace-before-keywordskeyword-spacingspace-return-throw-casekeyword-spacing其中keyword-spacing合并了三条空格类规则的能力负责强制关键字前后的一致间距。这些被移除的规则文档仍保留在仓库的 docs/src/rules/ 目录中如 no-arrow-condition.md、space-after-keywords.md 等便于查阅历史语义。值得一提的是keyword-spacing本身在后续版本中ESLint 8.53.0 起也被标记为 deprecated原因是格式化类规则正逐步移出 ESLint 核心其实现与废弃说明可以在 lib/rules/keyword-spacing.js 的meta中看到。配置级联Cascading行为变更变更内容在 v2.0.0 之前如果同一目录下同时存在.eslintrc文件与包含 ESLint 配置信息的package.json两份文件的设置会被合并。v2.0.0 之后当两者同时存在时只使用.eslintrc.*文件中的设置package.json中的 ESLint 配置被忽略只有在目录中不存在任何.eslintrc.*文件时package.json中的 ESLint 配置才会被使用。迁移改法如果同一目录下同时存在.eslintrc.*与带 ESLint 配置信息的package.json请将配置合并到其中一个文件中推荐保留.eslintrc.*避免配置二义性。这一就近优先、单一来源的思想在仓库后续的配置架构中得到了延续现代 flat config 通过 lib/config/flat-config-array.js 与 lib/config/flat-config-schema.js 实现更严格的配置合并与 schema 校验配置查找规则比 v2.0.0 时代更加明确。内置全局变量与es6环境变更内容v2.0.0 之前ES6 标准化的新全局变量如Promise、Map、Set、Symbol被直接包含在内置全局环境中。这带来一个隐患即使代码运行在 ES5 环境没有 Promise 可用no-undef也会放行Promise构造函数的使用。v2.0.0 之后内置环境仅包含标准 ES5 全局变量新增的 ES6 全局变量被移入es6环境。这一点在当前仓库的 conf/globals.js 中仍可验证Map、Promise、Set、Symbol、WeakMap、WeakSet等 ES6 全局对象被单独归类列出而不是混入 ES5 基础全局变量。迁移改法如果你在编写 ES6 代码需要显式开启es6环境如果尚未开启// 在 .eslintrc 中 { env: { es6: true, } } // 或者在配置注释中 /*eslint-env es6*/语言选项从ecmaFeatures到parserOptions变更内容v2.0.0 之前启用语言特性靠配置中的ecmaFeatures。v2.0.0 做了三项调整ecmaFeatures属性整体移入顶层parserOptions之下所有 ES6 相关的ecmaFeatures标志被移除统一由parserOptions.ecmaVersion取代其取值可为 3、5默认或 6ecmaFeatures.modules标志被parserOptions.sourceType取代取值为script默认或module用于 ES6 模块。被移除的 ES6 特性标志完整清单如下arrowFunctions—— 箭头函数binaryLiterals—— 二进制字面量blockBindings——let与const块级绑定classes—— class 类语法defaultParams—— 默认函数参数destructuring—— 解构赋值forOf——for-of循环generators—— 生成器modules—— 模块与全局严格模式objectLiteralComputedProperties—— 对象字面量计算属性名objectLiteralDuplicateProperties—— 严格模式下对象字面量重复属性objectLiteralShorthandMethods—— 对象字面量简写方法objectLiteralShorthandProperties—— 对象字面量简写属性octalLiterals—— 八进制字面量regexUFlag—— 正则表达式u标志regexYFlag—— 正则表达式y标志restParams—— 剩余参数rest parametersspread—— 数组展开运算符spread operatorsuperInFunctions—— 函数内部对super的引用templateStrings—— 模板字符串unicodeCodePointEscapes—— 码点转义code point escapes迁移改法如果你使用了上述任一 ES6 标志例如{ ecmaFeatures: { arrowFunctions: true, } }应改为通过ecmaVersion开启 ES6{ parserOptions: { ecmaVersion: 6, } }如果你使用的是非 ES6 标志如jsx需要把整个ecmaFeatures移入parserOptions{ ecmaFeatures: { jsx: true, } }改为{ parserOptions: { ecmaFeatures: { jsx: true, } } }如果你曾用ecmaFeatures.modules开启 ES6 模块支持{ ecmaFeatures: { modules: true, } }改为{ parserOptions: { sourceType: module, } }规则内部context用法的同步更新如果你的自定义规则内部使用了context.ecmaFeatures需要按以下方式更新若使用 ES6 特性标志如context.ecmaFeatures.blockBindings改写为检查context.parserOptions.ecmaVersion 5若使用context.ecmaFeatures.modules改写为检查 Program 节点的sourceType属性是否为module若使用非 ES6 特性标志如context.ecmaFeatures.jsx改写为检查context.parserOptions.ecmaFeatures.jsx。在后续引入 flat config 的版本中这类语言信息统一通过context.languageOptions暴露如context.languageOptions.ecmaVersion、context.languageOptions.sourceType。插件测试RuleTester的同步更新如果你的插件中包含使用ecmaFeatures的规则并且用 RuleTester 测试需要同步更新传入的选项。例如var ruleTester new RuleTester(); ruleTester.run(no-var, rule, { valid: [ { code: let x;, parserOptions: { ecmaVersion: 6 }, }, ], });如果你在配置、自定义/插件规则及其测试中均未使用ecmaFeatures则无需任何改动。eslint:recommended新增的 11 条规则v2.0.0 向eslint:recommended预设中新增了以下 11 条规则{ extends: eslint:recommended }新增规则清单constructor-superno-case-declarationsno-class-assignno-const-assignno-dupe-class-membersno-empty-patternno-new-symbolno-self-assignno-this-before-superno-unexpected-multilineno-unused-labels这批规则几乎都围绕 ES6 新语法class、解构、Symbol、标签等的易错场景设计与上文语言选项升级到 ES6的变更配套出现。迁移改法如果不想被这些规则提示可以显式关闭它们{ extends: eslint:recommended, rules: { no-case-declarations: 0, no-class-assign: 0, no-const-assign: 0, no-dupe-class-members: 0, no-empty-pattern: 0, no-new-symbol: 0, no-self-assign: 0, no-this-before-super: 0, no-unexpected-multiline: 0, no-unused-labels: 0, constructor-super: 0 } }作用域分析Scope Analysis变更变更内容v2.0.0 修复了作用域分析中的若干 bug此前对全局变量的定义方式处理不完整。原始设计中Variable对象与Reference对象互为引用Variable#references属性是一个Reference对象数组表示引用了该变量的所有引用Reference#resolved属性是被引用的Variable对象。但在 1.x 及以前以下几类变量和引用在上述属性中取的是错误的值空值全局作用域中的var声明全局作用域中的function声明配置文件中定义的变量/* global */注释中定义的变量。v2.0.0 之后这些变量与引用在上述属性中都有了正确的值。相应地Scope#through属性保存Reference#resolved为null的引用的值也因此发生变化。迁移改法如果你曾用Scope#through来查找内置全局变量需要改写代码。以查找window全局变量为例1.x 时代的绕路写法是var globalScope context.getScope(); globalScope.through.forEach(function (reference) { if (reference.identifier.name window) { checkForWindow(reference); } });之所以要绕道Scope#through是因为window的定义当时无法被正确找到它才被塞进了无法解析的引用集合中。v2.0.0 补回了正确的声明因此window不再位于Scope#through中可以直接从全局作用域的变量集合中取出并遍历其引用var globalScope context.getScope(); var variable globalScope.set.get(window); if (variable) { variable.references.forEach(checkForWindow); }这一修正使通过Scope#through反向找全局变量的 hack 不再必要全局变量的获取路径变得直接。仓库中的内置规则也大量沿用这套语义例如 lib/rules/camelcase.js 用scope.through遍历未定义全局变量// Undefined globalslib/rules/no-console.js 注释明确指出scope.through包含所有对未定义变量的引用并在console未定义时通过scope.through.filter(isConsole)兜底——这些都是 v2.0.0 作用域模型稳定之后的典型用法。作用域分析底层依赖 escope 生态相关接口见lib/languages/js/下的作用域相关实现如需深入了解可继续阅读仓库中关于作用域管理器的扩展文档 docs/src/extend/scope-manager-interface.md。使用eslint:recommended时的默认值变更此变更影响那些继承eslint:recommended并且只以严重级别方式开启no-multiple-empty-lines或func-style的配置例如{ extends: eslint:recommended, rules: { no-multiple-empty-lines: 2, func-style: 2 } }问题在于这两条规则在 1.x 中被eslint:recommended强加了与规则自身默认值相冲突的默认配置no-multiple-empty-lines规则本身没有默认例外但 1.x 的eslint:recommended给它套了一层默认值允许最多两个空行func-style规则自身默认配置为expression但 1.x 的eslint:recommended把它默认成了declaration。v2.0.0 移除了这些冲突的默认值因此升级后可能开始看到与这两条规则相关的 lint 错误。迁移改法如果想保持旧行为需要把默认值显式写进配置为no-multiple-empty-lines加上{max: 2}并把func-style改为declaration{ extends: eslint:recommended, rules: { no-multiple-empty-lines: [2, { max: 2 }], func-style: [2, declaration] } }从当前源码看lib/rules/no-multiple-empty-lines.js 的 schema 已支持max、maxEOF、maxBOF等多个整数参数required: [max]且不再内置任何来自 recommended 的隐性默认值——配置必须显式给出正是 v2.0.0 去除隐性默认的延续。SourceCode构造函数Node API的 BOM 处理变更内容v2.0.0 让SourceCode构造函数支持 Unicode BOM如果第一个参数text带有 BOM构造函数会把this.hasBOM设为true并从文本中剥离 BOM。var SourceCode require(eslint).SourceCode; var code new SourceCode(\uFEFFvar foo bar;, ast); assert(code.hasBOM true); assert(code.text var foo bar;);因此第二个参数ast也应当是基于剥离 BOM 之后的文本解析出来的。迁移改法如果你在自己的代码中使用SourceCode构造函数请先剥离 BOM 再解析源码var ast yourParser.parse(text.replace(/^\uFEFF/, ), options); var sourceCode new SourceCode(text, ast);这一 BOM 约定在当前仓库的实现中被完整保留在 lib/languages/js/source-code/source-code.js 的SourceCode构造函数中第 264 行起的类定义构造时通过text.charCodeAt(0) 0xfeff检测文本是否带 BOM设置this.hasBOM textHasBOM || !!hasBOM并以this.text textHasBOM ? text.slice(1) : text存储剥离 BOM 后的文本第 331–344 行。注释还专门说明了这一向后兼容的 BOM 处理Linter 会提前剥离 BOM并把hasBOM属性传给构造函数以简化各语言实现对 BOM 的处理。另外当前仓库中hasBOM属性还承担了规则层面的语义内置规则 lib/rules/unicode-bom.js 正是通过sourceCode.hasBOM来判断文件是否需要 BOMrequireBOM always时若没有 BOM 则报错never时有 BOM 则报错说明 BOM 状态已成为SourceCode公开且稳定的 API 属性。在 Linter 内部lib/linter/linter.js 的ensureText也通过hasBOM与text反向重组原始文本hasBOM ? \uFEFF text : text保证整条链路的信息不丢失。规则默认值变更strict规则strict规则的默认值从function改为safe。这一默认值在当前仓库中依然如此lib/rules/strict.js 中meta.defaultOptions: [safe]且 schema 支持[never, global, function, safe]四种取值。升级后如果沿用旧配置且未显式指定模式会收到行为差异相关的提示建议按需在配置中显式声明strict: [error, function]或strict: [error, safe]以明确预期。插件不再拥有默认配置rulesConfig被移除变更内容v2.0.0 之前插件可以在自身中通过rulesConfig指定默认配置任何人使用该插件时这些配置会被自动应用——这与 ESLint 在其他所有场景中默认什么都不开启的行为相悖。为了让插件行为与整体保持一致v2.0.0 移除了插件中的rulesConfig支持。迁移改法如果你在配置文件中使用了插件需要手动在配置文件中逐一开启该插件的规则。也就是说插件的规则默认关闭由使用方显式决定启用哪些规则及其选项从而让引入插件与生效规则两个动作彻底解耦。升级检查清单综合全文从 1.x 升级到 v2.0.0 时可按下表逐项核对变更项需要做的事规则 Schema移除严重级别项minItems改 0maxItems减 1已移除规则改用替代规则关注 CLI 输出的替代提示配置级联同一目录的.eslintrc.*与package.json配置二选一合并全局变量ES6 代码显式开启env: { es6: true }或/*eslint-env es6*/语言选项ecmaFeatures迁入parserOptionsES6 用ecmaVersion: 6模块用sourceType: module规则内contextcontext.ecmaFeatures.*改写为parserOptions/ ProgramsourceType判断RuleTester测试选项中改用parserOptions: { ecmaVersion: 6 }recommended 新增规则不需要的可显式关闭作用域分析全局变量改用globalScope.set.get(name).references不再走Scope#throughrecommended 默认值no-multiple-empty-lines显式加{max: 2}func-style显式declarationSourceCode传入构造函数的 AST 必须基于剥离 BOM 后的文本解析strict规则默认值变为safe按需显式声明插件手动开启插件规则rulesConfig不再生效v2.0.0 的绝大多数变更方向——规则自校验最小化、配置显式化、语言能力集中到parserOptions、作用域语义修正——都在当前仓库的源码与后续文档中得到了继承和强化理解这份迁移指南也就同时理解了现代 ESLint 配置与规则开发模型的设计来源。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考