遷移至 v5.0.0
ESLint v5.0.0 是第五個主要版本發布。我們在此版本中進行了一些重大變更,但我們預期大多數使用者都能夠在不修改其建置的情況下升級。本指南旨在引導您了解重大變更。
以下列表大致按每個變更預計影響的使用者數量排序,其中第一個項目預計影響最多使用者。
使用者的重大變更
- 不再支援 Node.js 4
- 已將新規則新增至
eslint:recommended
experimentalObjectRestSpread
選項已被棄用- 從命令列 Lint 不存在的檔案現在是嚴重錯誤
- 某些規則的預設選項已變更
- 已棄用的全域變數已從
node
、browser
和jest
環境中移除 - 現在會 Lint 空檔案
- 作用域套件中的外掛程式現在可在設定中解析
- 多行
eslint-disable-line
指令現在會回報為問題
外掛程式/自訂規則開發者的重大變更
- AST 節點的
parent
屬性現在會在規則開始執行前設定 - 當使用預設解析器時,展開運算子現在具有
SpreadElement
類型 - 當使用預設解析器時,其餘運算子現在具有
RestElement
類型 - 當使用預設解析器時,JSX 元素中的文字節點現在具有
JSXText
類型 context.getScope()
方法現在會傳回更適當的作用域- 規則 context 物件上的
_linter
屬性已被移除 RuleTester
現在在其斷言中使用嚴格相等檢查- 規則現在需要提供訊息以及報告
整合開發者的重大變更
不再支援 Node.js 4
截至 2018 年 4 月 30 日,Node.js 4 將達到 EOL,並且不再接收安全性更新。因此,我們已決定在 ESLint v5 中停止支援它。我們現在支援以下版本的 Node.js
- Node.js 6(6.14.0 及以上版本)
- Node.js 8(8.10.0 及以上版本)
- 任何高於 Node.js 9.10.0 的版本
解決方案: 確保在使用 ESLint v5 時升級至至少 Node.js 6。如果您無法升級,我們建議繼續使用 ESLint v4.x,直到您可以升級 Node.js 為止。
eslint:recommended
的變更
已將兩個新規則新增至 eslint:recommended
設定檔
for-direction
強制for
迴圈更新子句以正確的方向移動計數器。getter-return
強制屬性 getter 中存在return
陳述式。
解決方案: 若要模擬 4.x 中的 eslint:recommended
行為,您可以在設定檔中停用這些規則
{
"extends": "eslint:recommended",
"rules": {
"for-direction": "off",
"getter-return": "off"
}
}
experimentalObjectRestSpread
選項已被棄用
先前,當使用預設解析器時,可以使用 experimentalObjectRestSpread
選項來啟用對rest/spread 屬性的支援,如下所示
{
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
}
物件 rest/spread 現在是 JavaScript 語言的正式部分,因此我們對它的支援不再是實驗性的。在 ESLint v4 和 ESLint v5 中,物件 rest/spread 現在可以使用 "ecmaVersion": 2018
選項啟用
{
"parserOptions": {
"ecmaVersion": 2018
}
}
請注意,這也會啟用對 ES2018 中其他功能的解析,例如非同步迭代。當使用 ESLint v5 和預設解析器時,不再可能獨立於其他功能切換物件 rest/spread 的語法支援。
為了相容性,當在設定檔中找到 ecmaFeatures: { experimentalObjectRestSpread: true }
時,ESLint v5 會將其視為 ecmaVersion: 2018
的別名。因此,如果您使用物件 rest/spread,您的程式碼仍應能透過 ESLint v5 成功解析。但是,請注意,此別名將在 ESLint v6 中移除。
解決方案: 如果您使用 experimentalObjectRestSpread
選項,您應該能夠升級至 ESLint v5 而無需任何變更,但您會遇到棄用警告。若要避免警告,請在您的設定檔中使用 ecmaVersion: 2018
而不是 ecmaFeatures: { experimentalObjectRestSpread: true }
。如果您想要禁止使用其他 ES2018 功能,請考慮使用諸如no-restricted-syntax
之類的規則。
從命令列 Lint 不存在的檔案現在是嚴重錯誤
先前版本的 ESLint 會靜默忽略命令列上提供的任何不存在的檔案和 glob
eslint nonexistent-file.js 'nonexistent-folder/**/*.js' # exits without any errors in ESLint v4
許多使用者發現此行為令人困惑,因為如果他們在檔案名稱中輸入錯誤,ESLint 會顯示成功 lint 該檔案,但實際上並未 lint 任何內容。
當符合以下任一條件時,ESLint v5 會回報嚴重錯誤
- 命令列上提供的檔案不存在。
- 命令列上提供的 glob 或資料夾不符合任何可 lint 的檔案。
請注意,這也會影響 CLIEngine.executeOnFiles()
API。
解決方案: 如果您在升級至 ESLint v5 後遇到有關遺失檔案的錯誤,您可能需要仔細檢查您提供給 ESLint 的路徑中是否沒有錯字。若要讓錯誤消失,您可以簡單地從命令列上提供給 ESLint 的引數清單中移除給定的檔案或 glob。
如果您使用依賴此行為的樣板產生器(例如,在任何測試檔案實際存在之前,產生一個在新專案中執行 eslint tests/
的腳本),您可以透過新增符合給定模式的虛擬檔案(例如,一個空的 tests/index.js
檔案)來解決此問題。
某些規則的預設選項已變更
object-curly-newline
規則的預設選項已從{ multiline: true }
變更為{ consistent: true }
。no-self-assign
規則的預設選項物件已從{ props: false }
變更為{ props: true }
。
解決方案: 若要還原 ESLint v4 中的規則行為,您可以更新您的設定檔以包含先前的選項
{
"rules": {
"object-curly-newline": ["error", { "multiline": true }],
"no-self-assign": ["error", { "props": false }]
}
}
已棄用的全域變數已從 node
、browser
和 jest
環境中移除
某些全域變數已被棄用或從在 Node.js、瀏覽器和 Jest 中執行的程式碼中移除。(例如,瀏覽器過去會向 JavaScript 程式碼公開 SVGAltGlyphElement
全域變數,但此全域變數已從網路標準中移除,並且不再存在於瀏覽器中。)因此,我們已從對應的 eslint
環境中移除這些全域變數,因此當使用諸如 no-undef
之類的規則時,使用這些全域變數將會觸發錯誤。
解決方案: 如果您在 node
、browser
或 jest
環境中使用已棄用的全域變數,您可以將 globals
區段新增至您的設定,以重新啟用您需要的任何全域變數。例如
{
"env": {
"browser": true
},
"globals": {
"SVGAltGlyphElement": false
}
}
現在會 Lint 空檔案
ESLint v4 在 lint 僅包含空白字元的檔案時具有特殊行為:它會跳過執行解析器和規則,並且總是傳回零錯誤。這導致使用者和規則作者感到困惑,尤其是在為規則編寫測試時。(當編寫樣式規則時,規則作者偶爾會編寫一個原始碼僅包含空白字元的測試,以確保當找不到適用的程式碼時,規則行為正確。但是,像這樣的測試實際上根本不會執行規則,因此規則的某個方面最終會未經測試。)
ESLint v5 以與所有其他檔案相同的方式處理僅包含空白字元的檔案:它會解析它們並在它們上適當地執行已啟用的規則。如果您使用在空檔案上回報錯誤的自訂規則,這可能會導致額外的 lint 問題。
解決方案: 如果您的專案中有一個空檔案,並且您不希望它被 lint,請考慮將其新增至 .eslintignore
檔案。
如果您有自訂規則,您應該確保它能適當地處理空檔案。(在大多數情況下,應該不需要任何變更。)
作用域套件中的外掛程式現在可在設定中解析
當 ESLint v5 在設定中遇到以 @
開頭的外掛程式名稱時,該外掛程式將會解析為作用域 npm 套件。例如,如果設定檔包含 "plugins": ["@foo"]
,ESLint v5 將嘗試載入名為 @foo/eslint-plugin
的套件。(另一方面,ESLint v4 將嘗試載入名為 eslint-plugin-@foo
的套件。)這是一個重大變更,因為使用者可能一直依賴 ESLint 在 node_modules/eslint-plugin-@foo
找到套件。但是,我們認為不太可能有許多使用者依賴此行為,因為發布到 npm 的套件無法在中間包含 @
字元。
解決方案: 如果您依賴 ESLint 載入像 eslint-config-@foo
這樣的套件,請考慮將套件重新命名為其他名稱。
多行 eslint-disable-line
指令現在會回報為問題
eslint-disable-line
和 eslint-disable-next-line
指令註解僅允許跨越單行。例如,以下指令註解無效
alert('foo'); /* eslint-disable-line
no-alert */ alert('bar');
// (which line is the rule disabled on?)
先前,ESLint 會忽略這些格式錯誤的指令註解。ESLint v5 在看到像這樣的問題時會回報錯誤,以便可以更輕鬆地更正問題。
解決方案: 如果您因為此變更而看到新的回報錯誤,請確保您的 eslint-disable-line
指令僅跨越單行。請注意,「區塊註解」(以 /* */
分隔)仍然允許用於指令,前提是區塊註解不包含換行符號。
AST 節點的 parent
屬性現在會在規則開始執行前設定
先前,ESLint 會在執行該節點的規則監聽器之前立即在每個 AST 節點上設定 parent
屬性。這對規則作者造成了一些困惑,因為 parent
屬性最初不會出現在任何節點上,並且有時需要使規則的結構複雜化,以確保在需要時可以使用給定節點的 parent
屬性。
在 ESLint v5 中,parent
屬性在任何規則存取 AST 之前在所有 AST 節點上設定。這使得編寫某些規則更容易,因為 parent
屬性始終可用,而不是在幕後變更。但是,作為具有 parent
屬性的副作用,AST 物件在規則第一次看到它時具有循環結構(先前,它僅在第一個規則監聽器被呼叫後才具有循環結構)。因此,如果自訂規則列舉節點的所有屬性以遍歷 AST,則如果它未正確檢查循環,則現在可能會永遠循環或耗盡記憶體。
解決方案: 如果您編寫了一個列舉 AST 節點的所有屬性的自訂規則,請考慮排除 parent
屬性或實作循環偵測,以確保您獲得正確的結果。
當使用預設解析器時,展開運算子現在具有 SpreadElement
類型
先前,當使用啟用了 experimentalObjectRestSpread
選項的預設解析器解析像 const foo = {...data}
這樣的 JS 程式碼時,預設解析器會為 ...data
展開元素產生 ExperimentalSpreadProperty
節點類型。
在 ESLint v5 中,即使啟用了(現在已棄用的)experimentalObjectRestSpread
選項,預設解析器現在也始終為 ...data
AST 節點提供 SpreadElement
類型。這使得 AST 符合當前的 ESTree 規範。
解決方案: 如果您編寫了一個依賴於展開運算子具有 ExperimentalSpreadProperty
類型的自訂規則,您應該更新它以使其也適用於具有 SpreadElement
類型的展開運算子。
當使用預設解析器時,其餘運算子現在具有 RestElement
類型
先前,當使用啟用了 experimentalObjectRestSpread
選項的預設解析器解析像 const {foo, ...rest} = data
這樣的 JS 程式碼時,預設解析器會為 ...data
其餘元素產生 ExperimentalRestProperty
節點類型。
在 ESLint v5 中,即使啟用了(現在已棄用的)experimentalObjectRestSpread
選項,預設解析器現在也始終為 ...data
AST 節點提供 RestElement
類型。這使得 AST 符合當前的 ESTree 規範。
解決方案: 如果您編寫了一個依賴於其餘運算子具有 ExperimentalRestProperty
類型的自訂規則,您應該更新它以使其也適用於具有 RestElement
類型的其餘運算子。
當使用預設解析器時,JSX 元素中的文字節點現在具有 JSXText
類型
當解析像 <a>foo</a>
這樣的 JSX 程式碼時,預設解析器現在將為 foo
AST 節點提供 JSXText
類型,而不是 Literal
類型。這使得 AST 符合 JSX 規範的最新更新。
解決方案: 如果您編寫了一個依賴於 JSX 元素中的文字節點具有 Literal
類型的自訂規則,您應該更新它以使其也適用於具有 JSXText
類型的節點。
context.getScope()
方法現在會傳回更適當的作用域
先前,context.getScope()
方法根據 parserOptions.ecmaVersion
屬性變更其行為。但是,當使用不回應 ecmaVersion
選項的解析器(例如 babel-eslint
)時,這可能會導致令人困惑的行為。
此外,context.getScope()
在 CatchClause
(在 ES5 中)、ForStatement
(在 ≧ES2015 中)、ForInStatement
(在 ≧ES2015 中)、ForOfStatement
和 WithStatement
節點上錯誤地傳回了適當作用域的父作用域。
在 ESLint v5 中,context.getScope()
方法具有相同的行為,而與 parserOptions.ecmaVersion
無關,並且傳回適當的作用域。請參閱文件以取得有關傳回哪些作用域的更多詳細資訊。
解決方案: 如果您編寫了一個在節點處理常式中使用 context.getScope()
方法的自訂規則,您可能需要更新它以考慮修改後的作用域資訊。
規則 context 物件上的 _linter
屬性已被移除
先前,規則 context 物件具有未記載的 _linter
屬性,該屬性在 ESLint 內部用於處理來自規則的報告。某些規則使用此屬性來實現規則不應可能實現的功能。例如,多個外掛程式在規則中使用 _linter
屬性來監視來自其他規則的報告,以檢查是否有未使用的 /* eslint-disable */
指令註解。儘管此功能對使用者很有用,但它也可能對使用 ESLint 的專案造成穩定性問題。例如,一個外掛程式中規則的升級可能會意外地導致另一個外掛程式中的規則開始回報錯誤。
_linter
屬性已在 ESLint v5.0 中移除,因此不再可能使用此功能實作規則。但是,可以使用 --report-unused-disable-directives
CLI 旗標來標記未使用的指令註解。
RuleTester
現在在其斷言中使用嚴格相等檢查
先前,RuleTester
在進行某些斷言時使用寬鬆相等。例如,如果規則產生字串 "7"
作為自動修復的結果,RuleTester
將允許在 output
斷言中使用數字 7
,而不是字串 "7"
。在 ESLint v5 中,來自 RuleTester
的比較使用嚴格相等,因此像這樣的斷言將不再通過。
解決方案: 如果您使用 RuleTester
為您的自訂規則編寫測試,請確保您的斷言中的預期值與實際值嚴格相等。
規則現在需要提供訊息以及報告
先前,規則可以報告 AST 節點而不提供報告訊息。這不是預期的行為,因此,如果規則省略訊息,預設格式器將會崩潰。但是,當使用非預設格式器(例如 json
)時,可以避免崩潰。
在 ESLint v5 中,報告問題而不提供訊息總是會導致錯誤。
解決方案: 如果您編寫了一個報告問題而不提供訊息的自訂規則,請更新它以提供訊息以及報告。
source
屬性不再於個別的 lint 訊息上提供
如 2016 年 10 月 公告中所述,source
屬性已從個別的 lint 訊息物件中移除。
解決方案: 如果您的格式器或整合依賴於使用個別 lint 訊息上的 source
屬性,您應該更新它以改為使用檔案結果物件上的 source
屬性。
嚴重錯誤現在會導致結束代碼為 2
當使用 ESLint v4 時,以下兩種情況都會在命令列上執行 ESLint 時導致結束代碼為 1
- Lint 成功完成,但存在一些 lint 錯誤
- 由於嚴重錯誤(例如,無效的設定檔),Lint 失敗
因此,整合很難區分這兩種情況,以判斷是否應嘗試從輸出中擷取 lint 結果。
在 ESLint v5 中,由於嚴重錯誤導致的 Lint 失敗執行將導致結束代碼為 2,而不是 1。
解決方案: 如果您的整合透過檢查結束代碼是否等於 1 來偵測所有 lint 執行的問題,請更新它以檢查結束代碼是否為非零。
eslint.linter
屬性現在為不可列舉
當使用 ESLint 的 Node.js API 時,linter
屬性現在為不可列舉。請注意,linter
屬性已在 ESLint v4 中棄用,而改用 Linter
屬性。
解決方案: 如果您依賴於列舉 eslint
物件的所有屬性,請使用類似 Object.getOwnPropertyNames
的方法,以確保擷取到不可列舉的鍵。