概括
我们对我们的 ESLint 集成进行了改进,以支持使用新的扁平化配置的 ESLint v9。在此过程中,我们探索了许多新的可能性,使其更加个性化、强大,并提供更好的开发者体验。
您可以运行以下命令安装新的 @nuxt/eslint
模块
npx nuxi module add eslint
继续阅读故事或通过 文档 了解更多信息。
背景
ESLint 已成为当今 Web 开发中必不可少的工具。它可以帮助您捕获错误并在项目中强制执行一致的编码风格。在 Nuxt 中,我们尽最大努力为 ESLint 提供开箱即用的体验,使其易于使用、配置和遵循我们推荐的最佳实践。
由于 Nuxt 和 ESLint 都发生了很大的发展。从历史上看,我们最终在 Nuxt 中为 ESLint 创建了几个不同的包和集成,并且并不总是清楚哪个包用于什么目的。我们收到了来自社区的大量反馈。
为了改善这种情况并使其面向未来,我们最近刷新了我们的 ESLint 集成,以支持 ESLint v9 和 扁平化配置。它为自定义您的 ESLint 设置提供了更多功能,提供了更直接和统一的体验。
Nuxt ESLint 单仓
我们将分散在不同存储库中的与 ESLint 相关的包移动到一个单仓中:nuxt/eslint
,并提供了一个专门的新文档站点:eslint.nuxt.com。
为了帮助理解每个包之间的区别以及使用哪个包,我们还有一个 常见问题解答 页面,对它们进行比较并解释它们的范围。
此单仓现在包含
@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
功能使最终的配置结果难以理解和预测。这也使得共享配置难以维护和调试。
{
"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
包 中,我们利用我们拥有的灵活性来提供一个工厂函数,允许您以更高级的方式轻松自定义配置预设。以下是如何使用它的示例
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
export default createConfigForNuxt()
@nuxt/eslint-config
从非强制性基础配置开始,这意味着我们仅包含 TypeScript、Vue 和 Nuxt 的最佳实践规则,并将代码风格、格式化等其他内容留给您决定。您还可以并行运行 Prettier 以使用默认设置进行格式化。
该配置还允许您根据需要选择加入更多强制性功能。例如,如果您希望 ESLint 也处理格式化,则可以通过将 features.stylistic
传递给工厂函数来启用它(由 ESLint Stylistic 提供支持)
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
export default createConfigForNuxt({
features: {
stylistic: true
}
})
或使用选项对象调整您的首选项(在此处了解有关选项的更多信息)
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 模块开发的规则
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
实例
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.vue
、pages/index.vue
、layouts/default.vue
等文件在其他 Vue 文件中不可用作组件,并且该规则与它们无关。
通常,我们可以为这些文件关闭该规则,例如
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 规则将不太准确,并可能导致用户花费额外精力来手动保持一致。
类似地,我们希望仅对 pages
和 layouts
等启用 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 中,以便您在需要时轻松访问它。
检查器允许您查看已启用的最终解析的配置、规则和插件,并进行快速匹配以查看规则和配置如何应用于特定文件。它非常适合调试和了解 ESLint 在您的项目中的工作原理。
我们很高兴 ESLint 团队也发现它很有用,并且有兴趣将其提供给更广泛的 ESLint 社区。我们后来加入了这项工作,并将其打造成了 官方的 ESLint 配置检查器(顺便说一句,它是使用 Nuxt 构建的)。您可以阅读 这篇公告文章 以了解更多详细信息。
规则类型生成
配置 ESLint 的主要痛点之一是规则和配置的类型信息泄漏。很难知道特定规则有哪些可用选项,并且需要您来回切换文档以了解每个规则的选项。
再次感谢新的扁平化配置具有如此多的可能性。我们发现了一个新工具,eslint-typegen
,我们可以从中根据**您实际使用的插件**为每个规则的规则配置架构生成相应的类型。这意味着它是一个适用于任何 ESLint 插件的通用解决方案,并且类型始终准确且是最新的。
在 @nuxt/eslint
模块中,此功能开箱即用,因此您将立即获得这种很棒的体验
开发服务器检查器
借助新的模块,我们有机会将 @nuxtjs/eslint-module
和 dev server 的 ESLint 检查器合并到新的 @nuxt/eslint
模块中,作为一项可选功能。
要启用它,你可以在模块选项中将 checker
选项设置为 true
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/config-inspector
- 官方的 ESLint 配置检查器,为你的配置提供交互式 UI。eslint-typegen
- 根据你实际使用的插件生成 ESLint 规则的 TypeScript 类型。eslint-flat-config-utils
- 用于管理和组合 ESLint 扁平化配置的实用程序。
我们致力于支持更广泛的社区并与开发者合作改进这些工具并扩展其可能性。我们很高兴看到这些工具如何使 ESLint 生态系统受益并有助于整体的开发者体验。
未来
展望未来,我们渴望看到 ESLint 生态系统将如何继续发展,以及我们如何利用新的功能和可能性进一步增强 Nuxt 的开发者体验。我们致力于为 Nuxt 用户提供一个无缝且强大的开发环境,我们将继续探索新的想法并与社区合作以实现这一目标。