文章·  

Nuxt ESLint 整合煥新

我們改進了 ESLint 整合,以支援帶有 Flat Config 的 ESLint v9,以及一個具有更多功能的新模組。
Anthony Fu

Anthony Fu

@antfu

TL;DR

我們改進了 ESLint 整合,以支援帶有新 Flat Config 的 ESLint v9。在此過程中,我們探索了許多新的可能性,使其更具個性化、更強大,並提供更好的開發體驗。

您可以執行以下命令來安裝新@nuxt/eslint模組

終端
npx nuxi module add eslint

繼續閱讀故事或透過文件.

背景

ESLintESLint 已成為當今 Web 開發中不可或缺的工具。它能幫助您捕獲錯誤並在專案中強制執行一致的編碼風格。在 Nuxt,我們盡力為 ESLint 提供開箱即用的體驗,使其易於使用、配置並遵循我們推薦的最佳實踐。

自那以後,Nuxt 和 ESLint 都發展了很多。在過去,我們最終為 Nuxt 中的 ESLint 準備了幾個不同的包和整合,並且並非總是清楚哪個用於什麼目的。我們收到了社群的很多反饋。

為了改善這種情況並使其面向未來,我們最近更新了 ESLint 整合,以支援ESLint v9及其Flat Config。它為定製您的 ESLint 設定開闢了更多功能,提供了更直接、更統一的體驗。

Nuxt ESLint Monorepo

我們將分散在不同儲存庫中的 ESLint 相關包整合到一個單一的 Monorepo 中nuxt/eslint,併為此建立了一個專門的新文件網站eslint.nuxt.com.

為了幫助理解每個包之間的差異以及何時使用哪個包,我們還提供了一個常見問題頁面,其中比較了它們並解釋了它們的作用域。

這個 Monorepo 現在包括:

  • @nuxt/eslint - 適用於 Nuxt 3 的全新一體化 ESLint 模組,支援專案感知型 ESLint Flat Config 及更多功能。
  • @nuxt/eslint-config - 適用於 Nuxt 3 的非強制性但可定製的共享 ESLint 配置。同時支援Flat Config 格式等等和傳統格式.
  • @nuxt/eslint-plugin - 適用於 Nuxt 3 的 ESLint 外掛,提供 Nuxt 特定的規則和配置。
  • 兩個用於 Nuxt 2 的維護模式包。

ESLint Flat Config

在深入瞭解新的 Nuxt 整合之前,讓我向您介紹ESLint Flat Config.

的概念。Flat Config 是在 ESLint v8.21.0 中作為實驗性功能引入的配置格式,並在ESLint v9.

一個快速區分的參考:

  • Flat Config: eslint.config.js eslint.config.mjs 等。
  • Legacy Config: .eslintrc .eslintrc.json .eslintrc.js 等。

為什麼選擇 Flat Config?

ESLint 的這篇部落格文章詳細解釋了 Flat Config 系統的動機。簡而言之,傳統的 eslintrc 格式是在 JavaScript 的早期設計的,當時 ES 模組和現代 JavaScript 功能尚未標準化。其中涉及許多隱式約定,並且 extends 功能使得最終的配置結果難以理解和預測。這也使得共享配置難以維護和除錯。

.eslintrc
{
  "extends": [
    // Solve from `import("@nuxtjs/eslint-config").then(mod => mod.default)`
    "@nuxtjs",
    // Solve from `import("eslint-config-vue").then(mod => mod.default.configs["vue3-recommended"])`
    "plugin:vue/vue3-recommended",
  ],
  "rules": {
    // ...
  }
}

新的 Flat Config 將外掛和配置的解析從 ESLint 的內部約定轉移到原生的 ES 模組解析。這反過來使其更加明確和透明,甚至允許您從其他模組匯入它。由於 Flat Config 只是一個 JavaScript 模組,它也為更多的自定義打開了大門。

Flat Config 的 Nuxt 預設

在最新的@nuxt/eslint-config 包中,我們利用了其靈活性,提供了一個工廠函式,允許您以更高級別的方式輕鬆自定義配置預設。以下是您如何使用它的示例:

eslint.config.js
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'

export default createConfigForNuxt()

@nuxt/eslint-config 從一個非強制性的基礎配置開始,這意味著我們只包含了 TypeScript、Vue 和 Nuxt 的最佳實踐規則,而將程式碼風格、格式化等其餘部分留給您決定。您也可以同時執行Prettier進行格式化,使用預設設定。

該配置還允許您根據需要選擇啟用更多有主見的功能。例如,如果您希望 ESLint 也負責格式化,您可以透過將 features.stylistic 傳遞給工廠函式來啟用它(由ESLint Stylistic):

eslint.config.js
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'

export default createConfigForNuxt({
  features: {
    stylistic: true
  }
})

或者透過選項物件調整您的偏好(在此處瞭解更多選項):

eslint.config.js
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'

export default createConfigForNuxt({
  features: {
    stylistic: {
      semi: false,
      indent: 2, // 4 or 'tab'
      quotes: 'single',
      // ... and more
    }
  }
})

)。如果您正在編寫 Nuxt 模組,您可以啟用 features.tooling 來啟用 Nuxt 模組開發的規則。

eslint.config.js
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'

export default createConfigForNuxt({
  features: {
    tooling: true
  }
})

等等。Flat Config 中的工廠函式允許預設覆蓋底層 ESLint 配置的複雜性,併為終端使用者提供高階且使用者友好的抽象,以便進行自定義。所有這些都無需使用者擔心內部細節。

雖然這種方法透過最小化配置為您提供類似 Prettier 的體驗(因為它由 ESLint 提供支援),但您仍然可以根據需要完全靈活地自定義和覆蓋細粒度規則和外掛。

我們還利用eslint-flat-config-utils中的FlatConfigComposer工具,使覆蓋和擴充套件 Flat Config 變得更加容易。@nuxt/eslint-config/flat 中的工廠函式返回一個 FlatConfigComposer 例項。

eslint.config.js
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'

export default createConfigForNuxt({
  // ...options for Nuxt integration
})
  .append(
    // ...append other flat config items
  )
  .prepend(
    // ...prepend other flat config items before the base config
  )
  // override a specific config item based on their name
  .override(
    'nuxt/typescript', // specify the name of the target config, or index
    {
      rules: {
        // ...override the rules
        '@typescript-eslint/no-unsafe-assignment': 'off'
      }
    }
  )
  // an so on, operations are chainable

透過這種方法,我們兼顧了兩種優勢:易於使用的簡潔高階抽象,以及用於自定義和微調的強大功能。

Nuxt ESLint 模組

更進一步,我們為 Nuxt 3 製作了新的、一體化的@nuxt/eslint 模組。它利用 Nuxt 的上下文為您的專案生成專案感知和型別安全的 ESLint 配置。

專案感知規則

我們知道 Vue 的樣式指南建議對元件使用多詞名稱,以避免與現有和未來的 HTML 元素衝突。因此,在eslint-plugin-vue中,我們預設啟用了vue/multi-word-component-names規則。這是一個很好的實踐,但我們知道在 Nuxt 專案中,並非所有 .vue 檔案都註冊為元件。諸如 app.vuepages/index.vuelayouts/default.vue 等檔案不能作為其他 Vue 檔案中的元件使用,因此該規則與它們無關。

通常,我們可以為這些檔案關閉規則,例如

eslint.config.js
export default [
  {
    files: ['*.vue'],
    rules: {
      'vue/multi-word-component-names': 'error'
    }
  },
  {
    files: ['app.vue', 'error.vue', 'pages/**/*.vue', 'layouts/**/*.vue'],
    rules: {
      // disable the rule for these files
      'vue/multi-word-component-names': 'off'
    }
  }
]

它應該適用於大多數情況。然而,我們知道在 Nuxt 中,您可以自定義每個目錄的路徑層級允許您為每個目錄設定多個來源。這意味著 Linter 規則的準確性會降低,並且可能導致使用者需要額外的工作才能手動保持它們一致。

同樣,我們希望只對 pageslayouts 等啟用vue/no-multiple-template-root。隨著情況越來越多,要求使用者手動維護規則變得不切實際。

這就是 @nuxt/eslint 的魔力所在!它利用 Nuxt 的上下文來生成特定於您的專案結構的配置和規則。這與 Nuxt 提供的.nuxt/tsconfig.json非常相似,您現在也有了專案感知的 .nuxt/eslint.config.mjs 可以擴充套件。

要使用它,您可以將模組新增到您的 Nuxt 專案中

終端
npx nuxi module add eslint

配置檢查器 DevTools 整合

在遷移和研究新的 Flat Config 期間,我萌生了製作一個互動式 UI 檢查器來檢查 Flat Config 的想法,以使配置更加透明和易於理解。當您安裝了 @nuxt/eslint 模組時,我們已將其整合到Nuxt DevTools中,以便您可以隨時輕鬆訪問它。

該檢查器允許您檢視最終解析的配置、已啟用的規則和外掛,並進行快速匹配,以檢視規則和配置如何應用於特定檔案。它非常適合除錯和學習 ESLint 在您的專案中如何工作。

我們很高興 ESLint 團隊也認為它很有用,並有興趣將其推廣到更廣泛的 ESLint 社群。我們後來加入了這項工作,並將其製作成官方 ESLint 配置檢查器(順便說一下,它是用 Nuxt 構建的)。您可以閱讀此公告文章以獲取更多詳細資訊。

規則的型別生成

配置 ESLint 的主要痛點之一是規則和配置的型別資訊洩露。很難知道特定規則有哪些可用選項,您需要為每個規則查閱文件才能找出答案。

再次感謝新的 Flat Config 帶來了如此多的動態可能性。我們發現了一個新工具,eslint-typegen,我們可以根據您實際使用的外掛從每個規則的規則配置模式生成相應的型別。這意味著它是一個適用於任何 ESLint 外掛的通用解決方案,並且型別始終準確且最新。

@nuxt/eslint 模組中,此功能是開箱即用的,因此您將立即獲得這種出色的體驗。

開發伺服器檢查器

透過新模組,我們藉此機會將@nuxtjs/eslint-module以及 ESLint 的開發伺服器檢查器合併到新的 @nuxt/eslint 模組中,作為一項可選功能。

您可能大部分時間不需要此功能,因為您的編輯器整合應該已經在編輯器中提供了 ESLint 診斷。但是,對於某些使用不同編輯器並希望確保 ESLint 始終執行的團隊來說,能夠在開發伺服器中執行 ESLint 在某些情況下可能會有所幫助。

要啟用它,您可以在模組選項中將 checker 選項設定為 true

nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@nuxt/eslint'
  ],
  eslint: {
    checker: true // <---
  }
})

每當您遇到一些 ESLint 錯誤時,您會在控制檯和瀏覽器中看到警告。要了解有關此功能的更多資訊,您可以檢視文件.

模組鉤子

由於我們現在在 Nuxt 模組中擁有程式碼生成功能和專案感知配置,我們實際上可以用它做更多有趣的事情。其中之一是我們可以允許模組也對 ESLint 配置做出貢獻。想象一下,將來,當您安裝一個像 @nuxtjs/i18n 這樣的 Nuxt 模組時,它可以自動為與 i18n 相關的檔案啟用特定的 ESLint 規則;或者當您安裝像 @pinia/nuxt 這樣的模組時,它可以安裝 Pinia ESLint 外掛以強制執行 Pinia 的最佳實踐等。

作為一項實驗,我們製作了一個模組nuxt-eslint-auto-explicit-import,它可以利用預配置的 ESLint 預設,為 Nuxt 專案中註冊的自動匯入功能自動插入顯式匯入。這樣,您在使用 API 時仍然可以獲得與自動匯入相同的良好開發體驗,同時在程式碼庫中擁有自動插入的顯式匯入。

這仍處於早期階段,我們仍在探索可能性和最佳實踐。但我們對它所帶來的潛力感到非常興奮。我們將與社群合作,看看如何充分利用它。如果您有任何想法或反饋,請隨時與我們分享!

生態系統

在 Nuxt,我們一如既往地非常關心生態系統和社群。在我們探索採用新的 Flat Config 並改進開發體驗的過程中,我們製作了一些工具來實現這一目標。所有這些都是通用目的的,可以在 Nuxt 之外使用:

我們致力於支援更廣泛的社群,並與開發人員合作改進這些工具並擴充套件其可能性。我們很高興看到這些工具能為 ESLint 生態系統帶來益處,併為整體開發體驗做出貢獻。

未來

Flat Config 格式仍然相當新,ESLint v9 也才釋出幾周。外掛和社群正在逐漸跟上新格式。它仍處於探索和實驗階段。

展望未來,我們渴望看到 ESLint 生態系統將如何繼續發展,以及我們如何利用新功能和可能性來進一步提升 Nuxt 的開發體驗。我們致力於為 Nuxt 使用者提供無縫且強大的開發環境,並將繼續探索新想法並與社群合作以實現這一目標。