迁移到 v2.0.0
ESLint v2.0.0 是第二个主要版本发布。因此,在 ESLint 在 0.x 和 1.x 版本中的工作方式与未来版本的工作方式之间存在一些重大变化。这些变化是直接来自于 ESLint 用户社区的反馈,并且在充分考虑升级路径后才做出的。我们相信这些变化使 ESLint 变得更好,虽然升级需要做一些工作,但我们希望这次升级带来的痛苦足够小,让您能够看到升级的好处。
重要提示:如果您是从 0.x 版本升级,请参考 迁移到 1.0.0 作为您的起点。
规则 Schema 变更
由于规则 schema 工作方式的怪癖,如果选项足够复杂,您可能需要在规则 schema 中考虑规则的严重程度(0、1 或 2)。这将导致如下所示的 schema:
module.exports = {
"type": "array",
"items": [
{
"enum": [0, 1, 2]
},
{
"enum": ["always", "never"]
}
],
"minItems": 1,
"maxItems": 2
};
这对于规则开发者来说很困惑,因为规则似乎不应该负责验证自身的严重程度。在 2.0.0 版本中,规则不再需要检查自身的严重程度。
解决方法:如果您正在导出检查严重程度的规则 schema,则需要进行以下几项更改
- 从 schema 中移除严重程度
- 将
minItems
从 1 调整为 0 - 通过减 1 来调整
maxItems
以下是上面 schema 正确转换后的样子
module.exports = {
"type": "array",
"items": [
{
"enum": ["always", "never"]
}
],
"minItems": 0,
"maxItems": 1
};
移除的规则
以下规则已被弃用,并创建了新规则来替代它们。以下是已移除规则及其替代规则的列表
- no-arrow-condition 被 no-confusing-arrow 和 no-constant-condition 的组合所取代。启用这两个规则以获得与
no-arrow-condition
相同的功能。 - no-empty-label 被带有
{"allowLoop": true, "allowSwitch": true}
选项的 no-labels 所取代。 - space-after-keywords 被 keyword-spacing 所取代。
- space-before-keywords 被 keyword-spacing 所取代。
- space-return-throw-case 被 keyword-spacing 所取代。
解决方法:您需要更新您的规则配置以使用新规则。ESLint v2.0.0 还会在您使用已移除的规则时发出警告,并建议替换规则。希望这能减少升级过程中的意外情况。
配置级联变更
在 2.0.0 之前,如果一个目录同时包含 .eslintrc
文件和一个带有 ESLint 配置信息的 package.json
文件,则这两个文件中的设置会合并在一起。在 2.0.0 版本中,仅使用 .eslintrc.*
文件中的设置,当两者都存在时,package.json
中的设置将被忽略。否则,package.json
仍然可以与 ESLint 配置一起使用,但前提是不能存在其他 .eslintrc.*
文件。
解决方法:如果您的同一个目录中同时存在 .eslintrc.*
和带有 ESLint 配置信息的 package.json
,请将您的配置合并到其中一个文件中。
内置全局变量
在 2.0.0 之前,作为 ES6 标准化一部分的新全局变量(例如 Promise
、Map
、Set
和 Symbol
)包含在内置全局环境中。例如,即使在 promises 不可用的 ES5 代码中,no-undef
也允许使用 Promise
构造函数,这可能会导致潜在问题。在 2.0.0 版本中,内置环境仅包含标准的 ES5 全局变量,新的 ES6 全局变量已移至 es6
环境。
解决方法:如果您正在编写 ES6 代码,如果您尚未这样做,请启用 es6
环境
// In your .eslintrc
{
env: {
es6: true
}
}
// Or in a configuration comment
/*eslint-env es6*/
语言选项
在 2.0.0 之前,启用语言选项的方法是在您的配置中使用 ecmaFeatures
。在 2.0.0 版本中
ecmaFeatures
属性现在位于顶层parserOptions
属性下。- 所有 ECMAScript 6
ecmaFeatures
标志都已被移除,取而代之的是parserOptions
下的ecmaVersion
属性,可以将其设置为 3、5(默认)或 6。 ecmaFeatures.modules
标志已被parserOptions
下的sourceType
属性取代,可以将其设置为"script"
(默认)或"module"
用于 ES6 模块。
解决方法:如果您在 ecmaFeatures
中使用任何 ECMAScript 6 功能标志,您需要改用 ecmaVersion: 6
。ECMAScript 6 功能标志包括
arrowFunctions
- 启用 箭头函数binaryLiterals
- 启用 二进制字面量blockBindings
- 启用let
和const
(又名 块级绑定)classes
- 启用类defaultParams
- 启用 默认函数参数destructuring
- 启用 解构forOf
- 启用for-of
循环generators
- 启用 生成器modules
- 启用模块和全局严格模式objectLiteralComputedProperties
- 启用 计算对象字面量属性名objectLiteralDuplicateProperties
- 在严格模式下启用 重复对象字面量属性objectLiteralShorthandMethods
- 启用 对象字面量简写方法objectLiteralShorthandProperties
- 启用 对象字面量简写属性octalLiterals
- 启用 八进制字面量regexUFlag
- 启用 正则表达式u
标志regexYFlag
- 启用 正则表达式y
标志restParams
- 启用 剩余参数spread
- 启用数组的 展开运算符superInFunctions
- 在函数内部启用super
引用templateStrings
- 启用 模板字符串unicodeCodePointEscapes
- 启用 代码点转义
如果您正在使用任何这些标志,例如
{
ecmaFeatures: {
arrowFunctions: true
}
}
那么您应该使用 ecmaVersion
启用 ES6
{
parserOptions: {
ecmaVersion: 6
}
}
如果您在 ecmaFeatures
中使用任何非 ES6 标志,您需要将这些标志移到 parserOptions
内部。例如
{
ecmaFeatures: {
jsx: true
}
}
那么您应该将 ecmaFeatures
移到 parserOptions
下
{
parserOptions: {
ecmaFeatures: {
jsx: true
}
}
}
如果您像这样使用 ecmaFeatures.modules
来启用 ES6 模块支持
{
ecmaFeatures: {
modules: true
}
}
{
parserOptions: {
sourceType: "module"
}
}
此外,如果您在您的规则中使用 context.ecmaFeatures
,那么您还需要通过以下方式更新您的代码
- 如果您正在使用 ES6 功能标志,例如
context.ecmaFeatures.blockBindings
,请重写以检查context.parserOptions.ecmaVersion > 5
。 - 如果您正在使用
context.ecmaFeatures.modules
,请重写以检查 Program 节点的sourceType
属性是否为"module"
。 - 如果您正在使用非 ES6 功能标志,例如
context.ecmaFeatures.jsx
,请重写以检查context.parserOptions.ecmaFeatures.jsx
。
如果您的插件包含规则并且您正在使用 RuleTester,那么您还需要更新您为使用 ecmaFeatures
的规则传递的选项。例如
var ruleTester = new RuleTester();
ruleTester.run("no-var", rule, {
valid: [
{
code: "let x;",
parserOptions: { ecmaVersion: 6 }
}
]
});
如果您在您的配置或您的自定义/插件规则和测试中没有使用 ecmaFeatures
,则无需更改。
"eslint:recommended"
中的新规则
{
"extends": "eslint:recommended"
}
在 2.0.0 版本中,以下 11 条规则被添加到 "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
解决方法:如果您不想收到这些规则的通知,您可以简单地禁用这些规则。
{
"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
}
}
作用域分析变更
我们发现了一些作用域分析中的 Bug,需要解决。具体来说,我们没有正确地考虑全局变量在所有定义方式中的情况。
最初,Variable
对象和 Reference
对象相互引用
Variable#references
属性是一个Reference
对象数组,这些对象引用了该变量。Reference#resolved
属性是一个被引用的Variable
对象。
但在 1.x 版本之前,以下变量和引用在这些属性中具有错误的值(空)
- 全局作用域中的
var
声明。 - 全局作用域中的
function
声明。 - 在配置文件中定义的变量。
- 在
/* global */
注释中定义的变量。
现在,这些变量和引用在这些属性中具有正确的值。
Scope#through
属性具有 Reference#resolved
为 null
的引用。因此,作为此更改的结果,Scope#through
属性的值也发生了更改。
解决方法:如果您正在使用 Scope#through
来查找内置全局变量的引用,您需要进行以下几项更改。
例如,这是您在 1.x 版本中可能定位 window
全局变量的方式
var globalScope = context.getScope();
globalScope.through.forEach(function(reference) {
if (reference.identifier.name === "window") {
checkForWindow(reference);
}
});
这是一种迂回的方式来查找变量,因为它是由 ESLint 事后添加的。window
变量位于 Scope#through
中,因为找不到定义。
在 2.0.0 版本中,window
不再位于 Scope#through
中,因为我们已经添加回了正确的声明。这意味着您可以直接引用 window
对象(或任何其他全局对象)。因此,之前的示例将更改为这样
var globalScope = context.getScope();
var variable = globalScope.set.get("window");
if (variable) {
variable.references.forEach(checkForWindow);
}
进一步阅读:https://estools.github.io/escope/
使用 eslint:recommended
时的默认变更
如果您正在从 eslint:recommended
扩展,并且仅使用严重程度启用 no-multiple-empty-lines
或 func-style
,例如
{
"extends": "eslint:recommended",
"rules": {
"no-multiple-empty-lines": 2,
"func-style": 2
}
}
规则 no-multiple-empty-lines
没有默认例外,但在 ESLint 1.x
中,应用了来自 eslint:recommended
的默认值,使得最多允许两个空行。
规则 func-style
的默认配置为 "expression"
,但在 ESLint 1.x
中,eslint:recommended
将其默认为 "declaration"
。
ESLint 2.0.0 移除了这些冲突的默认值,因此您可能会开始看到与这些规则相关的代码检查错误。
解决方法:如果您想保持之前的行为,请通过添加 {"max": 2}
来更新您的 no-multiple-empty-lines
配置,并将 func-style
更改为 "declaration"
。例如
{
"extends": "eslint:recommended",
"rules": {
"no-multiple-empty-lines": [2, {"max": 2}],
"func-style": [2, "declaration"]
}
}
SourceCode 构造函数 (Node API) 变更
SourceCode
构造函数可以处理 Unicode BOM。如果第一个参数 text
具有 BOM,则 SourceCode
构造函数会将 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);
规则变更
strict
- 默认为"safe"
(之前的默认值为"function"
)
插件不再有默认配置
在 v2.0.0 之前,插件可以为插件指定 rulesConfig
。rulesConfig
会在有人使用该插件时自动应用,这与 ESLint 在其他所有情况下的行为相反(默认情况下什么都没有启用)。为了使插件行为保持一致,我们已移除对插件中 rulesConfig
的支持。
解决方法:如果您在您的配置文件中使用插件,您将需要在配置文件中手动启用插件规则。