通过 100 多个技巧集合学习 Nuxt!
文章·  

刷新后的 Nuxt ESLint 集成

我们改进了 ESLint 集成,以支持使用扁平配置的 ESLint v9,以及一个具有更多功能的新模块。

要点总结

我们改进了 ESLint 集成,以支持使用新的扁平配置的 ESLint v9。在此过程中,我们探索了许多新的可能性,使其更加个性化、强大,并具有更好的开发者体验。

您可以运行以下命令来安装新的 @nuxt/eslint 模块

终端
npx nuxi module add eslint

继续阅读故事,或通过 文档了解更多。

背景

ESLint 已成为当今 Web 开发的必备工具。它可以帮助您捕获错误并在项目中强制执行一致的编码风格。在 Nuxt,我们尽最大努力为 ESLint 提供开箱即用的体验,使其易于使用、配置并遵循我们推荐的最佳实践。

由于 Nuxt 和 ESLint 都得到了很大的发展。从历史上看,我们最终在 Nuxt 中有了 一些不同的 ESLint 包和集成,而且并非总是很清楚应该将哪个包用于什么目的。我们收到了来自社区的大量反馈。

为了改善这种情况并使其面向未来,我们最近刷新了 ESLint 集成以支持使用 扁平配置ESLint v9。它为自定义 ESLint 设置打开了更多功能,提供了更直接和统一的体验。

Nuxt ESLint Monorepo

我们将分散在不同存储库中的 ESLint 相关包移动到一个单独的 monorepo 中:nuxt/eslint,并有一个专门的新文档站点:eslint.nuxt.com

为了帮助理解每个包之间的差异以及应该使用哪个包,我们还提供了一个 FAQ 页面,对它们进行比较并解释其范围。

此 monorepo 现在包括

  • @nuxt/eslint - 用于 Nuxt 3 的新的多合一 ESLint 模块,支持项目感知的 ESLint 扁平配置等。
  • @nuxt/eslint-config - 用于 Nuxt 3 的不带偏见但可自定义的共享 ESLint 配置。支持 扁平配置格式旧版格式
  • @nuxt/eslint-plugin - 用于 Nuxt 3 的 ESLint 插件,提供 Nuxt 特定的规则和配置。
  • 用于 Nuxt 2 的两个处于维护模式的包。

ESLint 扁平配置

在深入了解新的 Nuxt 集成之前,让我向您介绍一下 ESLint 扁平配置的概念。

扁平配置是 ESLint v8.21.0 中作为实验性引入的一种配置格式,并成为 ESLint v9 中的默认格式。

快速参考以区分

  • 扁平配置: eslint.config.js eslint.config.mjs 等。
  • 旧版配置: .eslintrc .eslintrc.json .eslintrc.js 等。

为什么选择扁平配置?

ESLint 的这篇博客文章详细解释了扁平配置系统背后的动机。简而言之,旧的 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": {
    // ...
  }
}

新的扁平配置将插件和配置解析从 ESLint 的内部约定移至原生 ES 模块解析。这反过来使其更加显式和透明,甚至允许您从其他模块导入它。由于扁平配置只是一个 JavaScript 模块,它也为更多自定义打开了大门。

用于扁平配置的 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
  }
})

或者使用 options 对象调整您的偏好设置(在此处了解有关选项的更多信息

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
  }
})

等等。扁平配置中的工厂函数允许预设涵盖底层 ESLint 配置的复杂性,并为最终用户提供高级且用户友好的抽象以进行自定义。所有这一切都无需用户担心内部细节。

虽然这种方法为您提供了类似于 Prettier 的体验,并且配置最少(因为它由 ESLint 提供支持),但您仍然可以完全灵活地根据需要自定义和覆盖细粒度的规则和插件。

我们还从 eslint-flat-config-utils 中制作了一个 FlatConfigComposer 实用程序,使覆盖和扩展扁平配置更加容易。@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 集成

在为新的扁平配置进行迁移和研究期间,我想出了一个想法,即为扁平配置制作一个交互式 UI 检查器,使配置更加透明且易于理解。当您安装了 @nuxt/eslint 模块时,我们已将其集成到 Nuxt DevTools 中,以便您在需要时随时轻松访问它。

Screenshot of ESLint Config Inspector running as a tab in Nuxt DevTools

该检查器允许您查看已启用的最终解析配置、规则和插件,并进行快速匹配,以查看规则和配置如何应用于特定文件。它对于调试和了解 ESLint 在您的项目中的工作方式非常有用。

我们很高兴 ESLint 团队也发现它很有用,并且有兴趣将其用于更广泛的 ESLint 社区。我们后来加入了这项工作,并将其制作为 官方的 ESLint 配置检查器(顺便说一下,它是用 Nuxt 构建的)。您可以阅读 此公告帖子以了解更多详细信息。

规则的类型生成

配置 ESLint 的主要痛点之一是规则和配置的类型信息泄漏。很难知道特定规则有哪些可用选项,并且需要您跳转到每个规则的文档才能弄清楚。

再次感谢新的扁平配置的动态性和许多可能性。我们找到了一种新工具 eslint-typegen,我们可以基于您正在使用的实际插件,为每个规则从规则配置架构生成相应的类型。这意味着它是一种适用于任何 ESLint 插件的通用解决方案,并且这些类型始终准确且最新。

@nuxt/eslint 模块中,此功能是开箱即用的,因此您将立即获得这种出色的体验

Screenshot of VS Code that showcases the type check and autocomplete with ESLint rules config

开发服务器检查器

使用新模块,我们借此机会将 @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,它可以为您的 Nuxt 项目中注册的自动导入插入自动导入,并预配置了 ESLint 预设。这样,您在使用 API 进行自动导入时可以获得同样良好的开发体验,但仍然可以在您的代码库中使用自动插入的显式导入。

这仍然处于早期阶段,我们仍在探索可能性和最佳实践。但是我们对它的潜力和它带来的机会感到非常兴奋。我们将与社区合作,看看如何最大程度地利用它。如果您有任何想法或反馈,请随时与我们分享!

生态系统

在 Nuxt,我们一如既往地非常关心生态系统和社区。在探索采用新的扁平配置和改进开发人员体验的过程中,我们制作了一些工具来实现这一目标。它们都是通用的,可以在 Nuxt 之外使用

我们致力于支持更广泛的社区,并与开发人员合作改进这些工具并扩展其可能性。我们很高兴看到这些工具如何使 ESLint 生态系统受益,并为整体开发人员体验做出贡献。

未来

扁平配置格式仍然相当新,ESLint v9 几周前才刚刚发布。插件和社区正在逐渐适应新的格式。它仍处于探索和实验阶段。

展望未来,我们渴望看到 ESLint 生态系统将如何继续发展,以及我们如何利用新的功能和可能性来进一步增强 Nuxt 的开发人员体验。我们致力于为 Nuxt 用户提供无缝且强大的开发环境,我们将继续探索新的想法并与社区合作以实现这一目标。