惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
S
Schneier on Security
The Hacker News
The Hacker News
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
I
Intezer
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Schneier on Security
Schneier on Security
Security Latest
Security Latest
AWS News Blog
AWS News Blog
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
博客园 - 叶小钗
The Last Watchdog
The Last Watchdog
O
OpenAI News
月光博客
月光博客
Hacker News: Ask HN
Hacker News: Ask HN
阮一峰的网络日志
阮一峰的网络日志
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Latest news
Latest news
P
Palo Alto Networks Blog
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
PCI Perspectives
PCI Perspectives
博客园 - 聂微东
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
Forbes - Security
Forbes - Security
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
博客园 - 三生石上(FineUI控件)
Application and Cybersecurity Blog
Application and Cybersecurity Blog
罗磊的独立博客
WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security

The Nuxt Blog

Meet Nuxi · Nuxt Blog Introducing the Nuxt Agent · Nuxt Blog Nuxt 4.4 · Nuxt Blog Nuxt 4.3 · Nuxt Blog Building an MCP Server for Nuxt · Nuxt Blog Nuxt Image v2 · Nuxt Blog Nuxt 4.2 · Nuxt Blog Nuxt UI v4 · Nuxt Blog Nuxt 4.1 · Nuxt Blog Nuxt 3.18 · Nuxt Blog Announcing Nuxt 4.0 · Nuxt Blog Building a Privacy-First Feedback Widget · Nuxt Blog Roadmap to v4 · Nuxt Blog Nuxt 3.17 · Nuxt Blog Nuxt UI v3 · Nuxt Blog Nuxt 3.16 · Nuxt Blog Nuxt 3.15 · Nuxt Blog Introducing Nuxt Icon v1 · Nuxt Blog Nuxt 3.14 · Nuxt Blog Nuxt 3.13 · Nuxt Blog Introducing Nuxt Scripts · Nuxt Blog Nuxt 2 End-of-Life (EOL) · Nuxt Blog Nuxt 3.12 · Nuxt Blog Nuxt: Looking forward · Nuxt Blog Nuxt 3.11 · Nuxt Blog The Evolution of Shiki v1.0 · Nuxt Blog Nuxt 3.10 · Nuxt Blog Nuxt 3.9 · Nuxt Blog Nuxt DevTools v1.0 · Nuxt Blog Nuxt 3.8 · Nuxt Blog A New Website · Nuxt Blog Nuxt 3.7 · Nuxt Blog Nuxt on the Edge · Nuxt Blog Nuxt 3.6 · Nuxt Blog Nuxt 3.5 · Nuxt Blog Nuxt 3.4 · Nuxt Blog Introducing Nuxt DevTools · Nuxt Blog Nuxt 3.3 · Nuxt Blog Nuxt: A vision for 2023 · Nuxt Blog Announcing 3.0 · Nuxt Blog Announcing Nuxt 3 Release Candidate · Nuxt Blog Introducing Nuxt 3 Beta · Nuxt Blog Nuxt 2 Static Improvements · Nuxt Blog Going Full Static · Nuxt Blog Understanding how fetch works in Nuxt 2.12 · Nuxt Blog Nuxt 2: From Terminal to Browser · Nuxt Blog Introducing Smart Prefetching · Nuxt Blog Navigation · Nuxt Blog
Refreshed Nuxt ESLint Integrations · Nuxt Blog
2024-04-10 · via The Nuxt Blog

TL;DR

We revamped our ESLint integrations to support ESLint v9 with the new flat config. Along the way, we have explored many new possibilities to make it more personalized, powerful, and with better developer experience.

You can run the following command to install the new @nuxt/eslint module:

Terminal

npx nuxi module add eslint

Continue reading the story or learn more with the documentation.

Background

ESLint has become an essential tool for today's web development. It helps you to catch errors and enforce a consistent coding style in your project. At Nuxt, we do our best to provide an out-of-the-box experience for ESLint, making it easy to use, configure and follow the best practices we recommend.

Since, both Nuxt and ESLint have evolved a lot. Historically, we ended up with a few different packages and integrations for ESLint in Nuxt, and it wasn't always obvious which one to use for what purpose. We have received a lot of feedback from our community.

To improve the situation and also make it future-proof, we recently refreshed our ESLint integrations to support ESLint v9 with the flat config. It opens up many more capabilities for customizing your ESLint setup, providing a more straightforward and unified experience.

Nuxt ESLint Monorepo

We moved ESLint-related packages scattered across different repositories into a single monorepo: nuxt/eslint, with a dedicated new documentation site: eslint.nuxt.com.

To help understand the differences between each package and what to use, we also have a FAQ page comparing them and explaining their scopes.

This monorepo now includes:

  • @nuxt/eslint - The new, all-in-one ESLint module for Nuxt 3, supporting project-aware ESLint flat config and more.
  • @nuxt/eslint-config - The unopinionated but customizable shared ESLint config for Nuxt 3. Supports both the flat config format and the legacy format.
  • @nuxt/eslint-plugin - The ESLint plugin for Nuxt 3 provides Nuxt-specific rules and configurations.
  • Two packages for Nuxt 2 in maintenance mode.

ESLint Flat Config

Before diving into new Nuxt integrations, let me introduce you to the concept of ESLint flat config.

Flat config is a configuration format introduced in ESLint v8.21.0 as experimental, and became the default format in ESLint v9.

A quick reference to differentiate:

  • Flat config: eslint.config.js eslint.config.mjs etc.
  • Legacy config: .eslintrc .eslintrc.json .eslintrc.js etc.

Why Flat Config?

This blog post from ESLint explains the motivation behind the flat config system in detail. In short, the legacy eslintrc format was designed in the early time of JavaScript, when ES modules and modern JavaScript features were not yet standardized. Many implicit conventions involved, and the extends feature makes the final config result hard to understand and predict. Which also makes shared configs hard to maintain and debug.

.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": {
    // ...
  }
}

The new flat config moves the plugins and configs resolution from ESLint's internal convention to the native ES module resolution. This in turn makes it more explicit and transparent, allowing you to even import it from other modules. Since the flat config is just a JavaScript module, it also opens the door for much more customization.

Nuxt Presets for Flat Config

In the latest @nuxt/eslint-config package, we leverage the flexibility we have to provide a factory function that allows you to customize the config presets easily in a more high-level way. Here is an example of how you can use it:

eslint.config.js

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

export default createConfigForNuxt()

@nuxt/eslint-config starts with an unopinionated base config, which means we only include rules for best practices of TypeScript, Vue and Nuxt, and leave the rest like code style, formatting, etc for you to decide. You can also run Prettier alongside for formatting with the defaults.

The config also allows you to opt-in to more opinionated features as needed. For example, if you want ESLint to take care of the formatting as well, you can turn it on by passing features.stylistic to the factory function (powered by ESLint Stylistic):

eslint.config.js

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

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

Or tweak your preferences with an options object (learn more with the options here):

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

And if you are authoring a Nuxt Module, you can turn on features.tooling to enable the rules for the Nuxt module development:

eslint.config.js

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

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

...and so on. The factory function in flat config allows the presets to cover the complexity of the underlying ESLint configuration, and provide high-level and user-friendly abstractions for end users to customize. All this without requiring users to worry about the internal details.

While this approach offers you a Prettier-like experience with minimal configurations (because it's powered by ESLint), you still get the full flexibility to customize and override fine-grained rules and plugins as needed.

We also made a FlatConfigComposer utility from eslint-flat-config-utils to make it even easier to override and extend the flat config. The factory function in @nuxt/eslint-config/flat returns a FlatConfigComposer instance:

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

With this approach, we get the best of both worlds: the simplicity and high-level abstraction for easy to use, and the power for customization and fine-tuning.

Nuxt ESLint Module

Taking this even further, we made the new, all-in-one @nuxt/eslint module for Nuxt 3. It leverages Nuxt's context to generate project-aware and type-safe ESLint configurations for your project.

Project-aware Rules

We know that Vue's Style Guide suggests the use of multi-word names for components to avoid conflicts with existing and future HTML elements. Thus, in eslint-plugin-vue, we have the rule vue/multi-word-component-names enabled by default. It's a good practice to follow, but we know that in a Nuxt project, not all .vue files are registered as components. Files like app.vue, pages/index.vue, layouts/default.vue, etc. are not available as components in other Vue files, and the rule will be irrelevant to them.

Usually, we could turn off the rule for those files like:

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'
    }
  }
]

It should work for the majority of the cases. However, we know that in Nuxt you can customize the path for each directory, and layers allow you to have multiple sources for each directory. This means the linter rules will be less accurate and potentially cause users extra effort to keep them aligned manually.

Similarly, we want to have vue/no-multiple-template-root enabled only for pages and layouts, etc. As the cases grow, it becomes unrealistic to ask users to maintain the rules manually.

That's where the magic of @nuxt/eslint comes in! It leverages Nuxt's context to generate the configurations and rules specific to your project structure. Very similar to the .nuxt/tsconfig.json Nuxt provides, you now also have the project-aware .nuxt/eslint.config.mjs to extend from.

To use it, you can add the module to your Nuxt project:

Terminal

npx nuxi module add eslint

Config Inspector DevTools Integrations

During the migrations and research for the new flat config, I came up with the idea to make an interactive UI inspector for the flat config and make the configurations more transparent and easier to understand. We have integrated it into Nuxt DevTools when you have the @nuxt/eslint module installed so you easily access it whenever you need it.

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

The inspector allows you to see the final resolved configurations, rules and plugins that have been enabled, and do quick matches to see how rules and configurations have applied to specific files. It's great for debugging and learning how ESLint works in your project.

We are delighted that the ESLint team also finds it useful and is interested in having it for the broader ESLint community. We later joined the effort and made it the official ESLint Config Inspector (it's built with Nuxt, by the way). You can read this announcement post for more details.

Type Generation for Rules

One of the main pain points of configuring ESLint was the leak of type information for the rules and configurations. It's hard to know what options are available for a specific rule, and it would require you to jump around the documentation for every rule to figure that out.

Thanks again for the new flat config being dynamic with so many possibilities. We figured out a new tool, eslint-typegen, that we could generate the corresponding types from rules configuration schema for each rule based on the actual plugins you are using. This means it's a universal solution that works for any ESLint plugins, and the types are always accurate and up-to-date.

In the @nuxt/eslint module, this feature is integrated out-of-box, so that you will get this awesome experience right away:

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

Dev Server Checker

With the new module, we took the chance to merge the @nuxtjs/eslint-module and the dev server checker for ESLint into the new @nuxt/eslint module as an opt-in feature.

You might not need this feature most of the time, as your editor integration should already provide ESLint diagnostics right in your editor. However, for some teams that work with different editors and want to ensure ESLint is always running, being able to run ESLint within the dev server might be helpful in some cases.

To enable it, you can set the checker option to true in the module options:

nuxt.config.ts

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

Whenever you get some ESLint errors, you will see a warning in the console and the browser. To learn more about this feature, you can check the documentation.

Module Hooks

Since we are now in the Nuxt module with the codegen capabilities and the project-aware configurations, we can actually do a lot more interesting things with this. One is that we can allow modules to contribute to the ESLint configurations as well. Imagine that in the future, when you install a Nuxt module like @nuxtjs/i18n it can automatically enable specific ESLint rules for i18n-related files, or when you install something like @pinia/nuxt it can install the Pinia ESLint plugin to enforce the best practices for Pinia, etc.

As an experiment, we made a module nuxt-eslint-auto-explicit-import that can do auto inserts for the auto-imports registered in your Nuxt project with a preconfigured ESLint preset. So that you can get the same nice developer experience with auto-imports on using APIs, but still have the auto-inserted explicit imports in your codebase.

This is still in the early stages, and we are still exploring the possibilities and best practices. But we are very excited about the potential and the opportunities it opens up. We will collaborate with the community to see how we can make the most out of it. If you have any ideas or feedback, please do not hesitate to share them with us!

Ecosystem

At Nuxt, we care a lot about the ecosystem and the community as always. During our explorations to adopt the new flat config and improve the developer experience, we made quite a few tools to reach that goal. All of them are general-purposed and can be used outside of Nuxt:

We are committed to supporting the broader community and collaborating with developers to improve these tools and expand their possibilities. We are excited to see how these tools can benefit the ESLint ecosystem and contribute to the overall developer experience.

The Future

The flat config format is still fairly new, and ESLint v9 was just released a couple of weeks ago. Plugins and the community are gradually catching up to the new format. It's still in the phase of exploration and experimentation.

Looking ahead, we are eager to see how the ESLint ecosystem will continue to evolve and how we can leverage new capabilities and possibilities to further enhance Nuxt's developer experience. We are dedicated to providing a seamless and powerful development environment for Nuxt users, and we will continue to explore new ideas and collaborate with the community to achieve this goal.