
當我們在四月發布 ESLint v9.0.0 時,這是 30 個月以來的首次主要版本發布,並正式引入了新的 配置 系統。ESLint v9.0.0 也進行了一些 規則 API 變更,為核心的未來發展做準備。發布後,我們花費了大量時間 建立相容性工具、配置遷移工具,以及 規則 API 轉換工具,以協助生態系統遷移到 ESLint v9.0.0。所有這些工作對於我們繼續進行 ESLint 即將到來的下一個重大變革至關重要。
語言插件
兩年前,TSC 決定是時候開放 ESLint,使其能夠檢查 JavaScript 以外的語言。實際上,ESLint 核心的許多功能並非 JavaScript 特有:例如尋找和讀取檔案、載入檔案特定的配置、收集規則違規、將結果輸出到控制台等等。此外,我們不斷發現有插件在 ESLint 內部檢查其他語言(例如 GraphQL 和 HTML),並透過與 JavaScript 相同的邏輯傳遞不同的 AST。這既低效又容易出錯,而且必須有更好的方法。
在 2023 年,語言插件 RFC 獲得正式批准。然而,為了實施此 RFC,我們需要正式發布新的配置並進行一些規則 API 變更。特別是規則 API 變更,對於區分 ESLint 核心的功能和語言插件將為自訂規則提供的功能至關重要。在這兩項變更可用之後,我們開始了繁瑣的重構 ESLint 核心的工作,將 JavaScript 特有的部分從語言無關的部分中提取出來。
以下是未來發展的預期(沒有具體時間表,因為一切都取決於貢獻者的意願)
@eslint/js
- 我們將逐步將所有與 JavaScript 相關的功能移至@eslint/js
套件中,包括規則和文件。我們將重用現有的 Espree repo 並將其轉換為包含 Espree、eslint-scope
、eslint-visitor-keys
和所有核心 JavaScript 規則的 monorepo。這將使我們能夠在單一 repo 中處理所有與 JavaScript 相關的事務。@eslint/json
- 我們的第一個語言插件將允許 ESLint 原生檢查 JSON 檔案。此插件將包含解析邏輯以及所有相關規則和文件。與@eslint/js
類似,這將使我們能夠擁有一個專注於 JSON 檢查的單一 repo,進一步將任何語言特定的功能從核心中移出。@eslint/markdown
-eslint-plugin-markdown
將重新命名為@eslint/markdown
,以更好地與其他套件對齊。我們將新增檢查 Markdown 的能力和 Markdown 特定的規則。
目前的計畫是擁有這三個官方 ESLint 語言插件,並希望它們能作為生態系統開發更多語言插件的範例。
隨著語言特定的功能被提取到單獨的儲存庫中,我們剩下的任務就是完全重寫核心。
核心重寫
自 11 年前首次創建 ESLint 以來,ESLint 儲存庫中程式碼的架構沒有發生重大變化。因此,累積了許多技術債,阻礙了我們進行一些我們想做的變更。我們目前面臨的一些問題
- 同步核心邏輯。
Linter
類別是完全同步的,這意味著我們無法支援非同步規則或非同步解析,這兩項是我們經常收到的功能請求。我們需要新增一個非同步工作的第二個類別,或在Linter
中新增非同步工作的替代方法。這兩種選項看起來都是重要的工作,實際上等於重寫核心的大部分。 - 有限的 API。 公開 API 受到限制,因為 ESLint 最初並非旨在作為 API 使用。最初的
linter
物件僅用於啟用瀏覽器演示。後來它被Linter
類別取代,甚至更晚又出現了ESLint
類別,以完全模仿命令列介面。當我們想要公開新功能時,它需要存在於這兩個聽起來相似的 API 之一中,不幸的是,主要的決策點在於 API 是否需要在瀏覽器中可用。如果是,則它需要位於Linter
中,否則它需要位於ESLint
中。這既令人困惑,而且從長遠來看是不可持續的。 - 缺乏型別檢查。 我們一直希望在儲存庫中新增型別檢查,以幫助捕捉潛在問題,但過去嘗試這樣做需要大量的工作和協調。最終,我們得出的結論是這不值得付出努力。
- 停留在 CommonJS。 與型別檢查情況類似,雖然人們希望將程式碼庫轉換為 ESM,但這樣做所需的工作量令人卻步。我們將花費大量時間進行轉換,最終得到的只是一個等效的功能集。
在仔細考慮了持續增量變更現有核心或從頭開始的選項後,我們 決定 是時候從頭開始了。雖然我們堅信完全重寫代表著重大的風險,但在 11 年之後,我們可以誠實地說,我們已經從最初的架構中獲得了最大的收益。
展望未來,以下是您可以期待的
- 新的儲存庫。
eslint/rewrite
儲存庫是我們語言無關工作的新的家。這是一個 monorepo,我們將在其中管理所有與核心以某種方式直接相關的套件。 - 現代套件。
eslint/rewrite
中的每個套件都將達到現代標準,發布 ESM 入口點以及型別定義。在可能的情況下,我們也將發布 CommonJS 入口點。所有套件都發布了對 npm 和 JSR(如果適用)的出處證明。 - 與執行階段無關的核心。
@eslint/core
套件將包含 ESLint 的與執行階段無關的 API 以及核心的型別定義。我們將隨著時間的推移逐步構建此套件,因為我們設計新的 API,從eslint
套件中提取功能片段。隨著每年出現越來越多的 JavaScript 執行階段,我們認為與執行階段無關的核心變得越來越重要。 - 可組合的 API。 新的 API 將是可組合的,而不是將所有功能捆綁到一兩個類別中,而是使用許多專門構建的類別,旨在一起使用。類別將遵循單一職責原則,使其更容易進行變更並自訂整合中的 ESLint。
- 新的 CLI。 我們將在
@eslint/node
套件中從頭開始重寫 CLI。我們將從最常見的用例開始,並重新評估每個標誌,以確保它對於與語言無關的核心仍然有意義。使用不同的套件名稱使我們能夠試驗新的 CLI,而不會干擾eslint
套件的使用。此套件也將匯出其他特定於 Node.js 的 API。 - 並行開發。 我們將繼續並行維護
eslint
和重寫,這樣我們就不會為了全新的東西而犧牲現有的套件。目標是讓eslint
套件逐漸變小,並使用@eslint/core
中包含的 API,以便我們盡可能地限制重複。
結論
我們對 ESLint 的未來方向感到非常興奮,因為我們認為這代表了 ESLint 發展的下一個邏輯步驟。將 ESLint 轉變為任何人都可為其編寫插件的語言無關的 linter 將透過減少任何一個專案所需的檢查工具和編輯器擴充功能的數量來簡化開發。此外,將我們的核心重寫為更可組合的 API 可以實現更輕鬆、更可自訂的整合,並擁有我們自己的型別定義,以確保與 API 的相容性。
ESLint 以其目前的架構走過了 11 年,我們希望這些變更將幫助我們度過接下來的 11 年。