news 2026/9/13 8:06:54

ESLint v2.0.0 迁移指南:从 0.x/1.x 升级到第二个大版本的完整变更解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESLint v2.0.0 迁移指南:从 0.x/1.x 升级到第二个大版本的完整变更解析

ESLint v2.0.0 迁移指南:从 0.x/1.x 升级到第二个大版本的完整变更解析

【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint

ESLint 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 中参与校验。这会导致出现如下形式的 schema:

module.exports = { type: "array", items: [ { enum: [0, 1, 2], }, { enum: ["always", "never"], }, ], minItems: 1, maxItems: 2, };

这种做法让规则开发者感到困惑——严重级别是 ESLint 核心机制的一部分,本不该由每条规则自己去验证。因此在 v2.0.0 中,规则不再需要检查自己的严重级别。

迁移改法

如果你导出的规则 schema 中包含对严重级别的校验,需要做三处修改:

  1. 从 schema 中移除严重级别那一项;
  2. minItems从 1 调整为 0;
  3. maxItems减去 1。

上面示例正确转换后的 schema 为:

module.exports = { type: "array", items: [ { enum: ["always", "never"], }, ], minItems: 0, maxItems: 1, };

从当前仓库的实现看,现代规则普遍采用meta.defaultOptionsmeta.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-spacing
space-before-keywordskeyword-spacing
space-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 标准化的新全局变量(如PromiseMapSetSymbol)被直接包含在内置全局环境中。这带来一个隐患:即使代码运行在 ES5 环境(没有 Promise 可用),no-undef也会放行Promise构造函数的使用。v2.0.0 之后,内置环境仅包含标准 ES5 全局变量,新增的 ES6 全局变量被移入es6环境。

这一点在当前仓库的 conf/globals.js 中仍可验证:MapPromiseSetSymbolWeakMapWeakSet等 ES6 全局对象被单独归类列出,而不是混入 ES5 基础全局变量。

迁移改法

如果你在编写 ES6 代码,需要显式开启es6环境(如果尚未开启):

// 在 .eslintrc 中 { env: { es6: true, } } // 或者在配置注释中 /*eslint-env es6*/

语言选项:从ecmaFeaturesparserOptions

变更内容

v2.0.0 之前,启用语言特性靠配置中的ecmaFeatures。v2.0.0 做了三项调整:

  • ecmaFeatures属性整体移入顶层parserOptions之下;
  • 所有 ES6 相关的ecmaFeatures标志被移除,统一由parserOptions.ecmaVersion取代,其取值可为 3、5(默认)或 6;
  • ecmaFeatures.modules标志被parserOptions.sourceType取代,取值为"script"(默认)或"module"(用于 ES6 模块)。

被移除的 ES6 特性标志完整清单如下:

  • arrowFunctions—— 箭头函数
  • binaryLiterals—— 二进制字面量
  • blockBindings——letconst块级绑定
  • classes—— class 类语法
  • defaultParams—— 默认函数参数
  • destructuring—— 解构赋值
  • forOf——for-of循环
  • generators—— 生成器
  • modules—— 模块与全局严格模式
  • objectLiteralComputedProperties—— 对象字面量计算属性名
  • objectLiteralDuplicateProperties—— 严格模式下对象字面量重复属性
  • objectLiteralShorthandMethods—— 对象字面量简写方法
  • objectLiteralShorthandProperties—— 对象字面量简写属性
  • octalLiterals—— 八进制字面量
  • regexUFlag—— 正则表达式u标志
  • regexYFlag—— 正则表达式y标志
  • restParams—— 剩余参数(rest parameters)
  • spread—— 数组展开运算符(spread operator)
  • superInFunctions—— 函数内部对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,需要按以下方式更新:

  1. 若使用 ES6 特性标志(如context.ecmaFeatures.blockBindings),改写为检查context.parserOptions.ecmaVersion > 5
  2. 若使用context.ecmaFeatures.modules,改写为检查 Program 节点的sourceType属性是否为"module"
  3. 若使用非 ES6 特性标志(如context.ecmaFeatures.jsx),改写为检查context.parserOptions.ecmaFeatures.jsx

(在后续引入 flat config 的版本中,这类语言信息统一通过context.languageOptions暴露,如context.languageOptions.ecmaVersioncontext.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-super
  • no-case-declarations
  • no-class-assign
  • no-const-assign
  • no-dupe-class-members
  • no-empty-pattern
  • no-new-symbol
  • no-self-assign
  • no-this-before-super
  • no-unexpected-multiline
  • no-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#resolvednull的引用)的值也因此发生变化。

迁移改法

如果你曾用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 globals),lib/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-linesfunc-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 已支持maxmaxEOFmaxBOF等多个整数参数(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来判断文件是否需要 BOM(requireBOM === "always"时若没有 BOM 则报错,"never"时有 BOM 则报错),说明 BOM 状态已成为SourceCode公开且稳定的 API 属性。在 Linter 内部(lib/linter/linter.js 的ensureText),也通过hasBOMtext反向重组原始文本(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改 0,maxItems减 1
已移除规则改用替代规则,关注 CLI 输出的替代提示
配置级联同一目录的.eslintrc.*package.json配置二选一合并
全局变量ES6 代码显式开启env: { es6: true }/*eslint-env es6*/
语言选项ecmaFeatures迁入parserOptions,ES6 用ecmaVersion: 6,模块用sourceType: "module"
规则内contextcontext.ecmaFeatures.*改写为parserOptions/ ProgramsourceType判断
RuleTester测试选项中改用parserOptions: { ecmaVersion: 6 }
recommended 新增规则不需要的可显式关闭
作用域分析全局变量改用globalScope.set.get(name).references,不再走Scope#through
recommended 默认值no-multiple-empty-lines显式加{"max": 2}func-style显式"declaration"
SourceCode传入构造函数的 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 8:06:22

无广告AI对话平台的商业价值与技术实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 8:06:15

多模型融合与贝叶斯优化在时间序列预测中的应用

1. 项目概述:多模型融合的贝叶斯优化预测方案这个项目本质上是在解决一个经典的时间序列预测问题——如何利用历史多变量数据准确预测未来值。我们采用了三种不同的深度学习模型架构(CNN-BiLSTM、BiLSTM以及它们的贝叶斯优化版本)&#xff0c…

作者头像 李华
网站建设 2026/9/13 8:04:48

AI编程规范:让生成代码可理解、可维护、可演进

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 8:00:50

SpringBoot教务管理系统设计与实践

1. 项目背景与核心需求教务管理系统是高校信息化建设的核心组成部分,它直接关系到教学管理的效率和质量。传统教务管理往往面临以下痛点:数据孤岛现象严重,各部门信息无法实时共享手工操作比例高,排课、成绩录入等环节易出错师生服…

作者头像 李华
网站建设 2026/9/13 7:59:59

Spring Boot XSS拦截器实战:防护设计与性能优化

1. Spring Boot XSS拦截器实战背景在Web应用开发中,XSS(跨站脚本攻击)长期位居OWASP Top 10安全威胁前列。去年某电商平台就因未做有效防护,导致攻击者通过商品评价区注入恶意脚本,窃取了上万用户的登录凭证。这类攻击…

作者头像 李华