DEV Community

Cover image for Guide to ESLint & Prettier with Nuxt 3
Nikita
Nikita

Posted on

Guide to ESLint & Prettier with Nuxt 3

Introduction

In this article, you will learn:

  1. How to set up a Nuxt project with ESLint and Prettier
  2. How to configure ESLint and Prettier together
  3. How ESLint plugins and configs work
  4. The difference between plugins and extends in ESLint
  5. How Prettier plugins work
  6. Other important details

Prerequisites

You should have basic knowledge of Prettier and ESLint. You'll also need VS Code, but if you don't have that, it's not a problem as long as you really know the basics about your particular IDE.

Environment Preparation

If you're using a separate IDE from VSCode, you can skip this part. ESLint and Prettier follow the same script in every IDE. If you are a VSCode user, let's get started.

First of all install these 2 extensions:

  1. Prettier - Code formatter Prettier - Code formatter
  2. ESLint ESLint

Now open VSCode settings using CTRL + , hotkey in Windows or using the panel below:
VSCode

Open settings.json. You can find the button in the top right corner
VSCode

Then add or change the following parameters:

{
  "prettier.configPath": ".prettierrc",
  "editor.formatOnPaste": false,
  "editor.formatOnType": false,
  "scss.lint.unknownAtRules": "ignore",
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "eslint.format.enable": true,
  "prettier.useEditorConfig": false
}
Enter fullscreen mode Exit fullscreen mode

Useful Note. If you want to see what each of these settings does, then go back to the convenient UI window with settings and enter the keys (from settings.json) into the search one by one, for example:
Image description

Project Initialization

Now go to the terminal and select the folder you like to create the project
Terminal

To initialize the nuxt project you must run the following command:

npx nuxi@latest init my-project
Enter fullscreen mode Exit fullscreen mode

Useful Note. If you want to deploy the nuxt project exactly in the current folder, and not create a new one with the project, then run npx nuxi@latest init ./ (as in my case)
Image description
As you can see, the project is deployed directly in the selected folder. As for me, in some cases this is a way more convenient than nuxt creating a new folder for the project

Now let's install the common dependencies:

npm i -D prettier eslint
Enter fullscreen mode Exit fullscreen mode

Useful Note. The -D flag is used to add a package to devDependencies. You can read more here

I think you already know how Prettier and ESLint work without each other, but if not, be sure to check it out before we go any further.

Integrate ESLint module to Nuxt

You can just follow this guide and skip this section, but if you want, let's walk through it together.

In your nuxt application install

npm add -D @nuxtjs/eslint-module
Enter fullscreen mode Exit fullscreen mode

Useful Note. npm add is exactly the same command as npm i, but it just looks nicer from a naming point of view. That is, it’s like an alias

In essence, this action simply adds a plugin to the nuxt application (in addition to ESLint, you can add any other from here). This setting is purely for nuxt so that it knows which modules you are using, so now you need to edit nuxt.config.ts and add just one line to it

modules: ["@nuxtjs/eslint-module"]
Enter fullscreen mode Exit fullscreen mode

Now your nuxt.config.ts should look something like this

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: ["@nuxtjs/eslint-module"],
})
Enter fullscreen mode Exit fullscreen mode

Plugins and configs in ESLint

Remember one thing - plugins do not configure your ESLint in any way. You just sort of add a module to it, but don't connect it. This can be compared to regular projects. For example, you can add a large jquery folder to the project (I hope you haven’t had this experience), and connect only jquery.min.js to the project from the folder. And here the jquery folder is a plugin, and jquery.min.js is a config. That is, when you specify something in plugins in ESLint, you simply load some rules and you need to configure which ones work.

All plugin names begin with eslint-plugin-. Having any plugin installed, for example eslint-plugin-react, you can connect it with removed prefix, like here

plugins: [
  "react", // the same as "eslint-plugin-react"
]
Enter fullscreen mode Exit fullscreen mode

But you can use a longer way:

plugins: [
  "eslint-plugin-react", // the same as "eslint-plugin-react"
]
Enter fullscreen mode Exit fullscreen mode

I also would like to say about plugins starting with @. Let's introduce the child plugins @foo/eslint-plugin and @foo/eslint-plugin-bar. And you can connect these plugins in the following ways:

"plugins": [
      "@foo/eslint-plugin-bar", // the same as "@foo/eslint-plugin-bar"
      "@foo/bar",           // the same as "@foo/eslint-plugin-bar"
      "@foo/eslint-plugin",        // the same as "@foo/eslint-plugin"
      "@foo"        // the same as "@foo/eslint-plugin"
    ]
Enter fullscreen mode Exit fullscreen mode

And here ESLint works quickly, but I wouldn’t say it’s good, because often confusion arises due to such moments. Therefore, carefully study the example above and make sure that everything is clear.

Well, I hope you have mastered the information above and now let's talk about extends. In extends we always specify the configuration of our plugins. You can specify the entire configuration yourself in a separate place and add just this one file to extends. But this practice is very inconvenient and generally makes no sense when there are already ready-made configurations. In general, with plugins you simply load a preset, and with configs you connect the necessary settings for this preset. Configs start with eslint-config- (similar to plugins), but configs can also be inside plugins, and to use them you must set the appropriate plugin: prefix. I understand that it has become more difficult now, so let’s immediately analyze everything we’ve covered using the example of our application.

In the beginning we just included ESLint in the nuxt project, but ESLint does not have any settings for nuxt at the moment and the most useful plugin for nuxt is eslint-plugin-nuxt. Let's install it:

npm i -D eslint-plugin-nuxt
Enter fullscreen mode Exit fullscreen mode

Now let's create a .eslintrc.json file in the project root

Project Root

Let's add this plugin to our .eslintrc.json

{
   "plugins": ["nuxt"] // the same as "eslint-plugin-nuxt"
}
Enter fullscreen mode Exit fullscreen mode

Now let's add a new script to package.json:

"lint": "eslint .",
Enter fullscreen mode Exit fullscreen mode

Now it looks like this
VSCode

Let's try to run this script and we'll get the following error:
Terminal

ESLint requires us to include a config, so let's do that, but first let's have a look at the open source of this plugin and find the recommended.js file
eslint-plugin-nuxt/recommended

As you can see, here are the usual ESLint settings (as in any other config), and all because this is essentially a .eslintrc.json file, only encrypted in js format. and it extends base.js, let's look at that too
eslint-plugin-nuxt/base

And here you can see the plugin connection

plugins: [
    'nuxt' // the same as "eslint-plugin-nuxt"
],
Enter fullscreen mode Exit fullscreen mode

That is, this config connects the main plugin eslint-plugin-nuxt and configures it by specifying various parameters (for example, connecting rules). You can literally copy this config and paste it into your .eslintrc.json and everything will work for you. Here's a minimalistic example of config, which just control single rule from the plugin

{
    "plugins": [
        "nuxt"
    ],
    "rules": {
        "nuxt/rule-name": 2
    }
}
Enter fullscreen mode Exit fullscreen mode

But again, it’s inconvenient to configure everything yourself and each plugin already has ready-made configs, like this recommended.js. So we can simply use them based on the plugin documentation. If you know OOP and programming, then you know the extend operation from there, and here it works similarly. Well, now let's write the config connection for the plugin

{
  "extends": [
    "plugin:eslint-plugin-nuxt/recommended"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Remember what I said about the plugin: prefix? This is where it is used, since the config is loaded directly from the plugin. In this case, we may not add the plugin connection to plugins "plugins": ["nuxt"]. As mentioned above, also we can omit eslint-plugin- and we get

{
  "extends": [
    "plugin:nuxt/recommended"
  ]
}
Enter fullscreen mode Exit fullscreen mode

But this config is already deprecated, and we can connect another one that includes its own npm package. Let's install @nuxt/eslint-config and connect in .prettierrc.json

npm add -D @nuxt/eslint-config 
Enter fullscreen mode Exit fullscreen mode

And extend it in .eslintrc.json

{
   "extends": [
     "@nuxt" // The same as @nuxt/eslint-config
   ]
}
Enter fullscreen mode Exit fullscreen mode

Now let's write the following code in app.vue:

<template>
  <div>
    <div class="hello"></div>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

And run the npm run lint command
VS Code

As you can see ESLint works now! You can experiment with the name of the extended config
VS Code

Also let's look at the repository of this config
@nuxt/eslint-config

Here we are using the basic eslint-config, but as you can see there are other options, such as eslint-config-legacy, which works for older versions, etc. But if you try to connect it by simply writing something like this, nothing will work

{
   "extends": [
     "@nuxtjs/eslint-config-legacy-typescript"
   ]
}
Enter fullscreen mode Exit fullscreen mode

That's because this config only works for version 2 of nuxt, as you can verify through the code on github:
@nuxt/eslint-config-legacy

In general, keep in mind that each plugin has its own internal structure, and you need to delve into open source to connect everything correctly. As a result, you can notice that we installed only one plugin eslint-plugin-nuxt, and we can connect different configs to it (plugin:prettier/recommended, which comes in the box with the plugin and @nuxt/eslint-config, which is installed separately). So there are no restrictions here, you can customize any plugins individually and write your own configs. And if you, for example, connected a config and want to override some settings, then simply specify them in the root .eslintrc.json. But consider the order in which you extend your configs! The order of the configurations in the extends array matters. The configurations listed later will override conflicting rules from earlier configurations.

module.exports = {
  extends: [
    'eslint:recommended', // Base configuration
    'plugin:react/recommended', // Extending a specific plugin configuration
    'airbnb', // Extending a third-party configuration
    'prettier', // Extending a configuration for code formatting
  ],
  rules: {
    // Your additional or overridden rules go here
  },
};
Enter fullscreen mode Exit fullscreen mode

Prettier & ESlint

There are 2 packages: eslint-plugin-prettier and eslint-config-prettier. They eliminate potential conflicts between ESLint and Prettier for your application and give ESLint the ability to follow the rules in Prettier. Always connect them together, otherwise conflicts will arise. They complement each other. Let's connect them

npm add -D eslint-plugin-prettier eslint-config-prettier
Enter fullscreen mode Exit fullscreen mode

And now we add the corresponding configs to extends

{
  "extends": ["@nuxt", "plugin:prettier/recommended", "prettier"] // The same as "@nuxt/eslint-config", "plugin:eslint-plugin-prettier/recommended", "eslint-config-prettier"
}
Enter fullscreen mode Exit fullscreen mode

In general, we are finished, but we still need to add the following parameters to .eslintrc.json for it to work correctly

{
  "extends": ["@nuxt", "plugin:prettier/recommended", "prettier"], // The same as "@nuxt/eslint-config", "plugin:eslint-plugin-prettier/recommended", "eslint-config-prettier"
  "env": {
    "browser": true,
    "node": true,
 },
}
Enter fullscreen mode Exit fullscreen mode

Configure .prettierc

Now let's create just an empty .prettierrc file

VS Code

Open app.vue
VS Code

In VSCode go to command palette:
VS Code

Restart ESLint server. This procedure is needed simply to update ESLint in VS Code
VS Code

And now if you remove the space, ESLint will start displaying an error related to prettier
VS Code

Now go back to the command palette and select format document
VS Code
VS Code

The document is formatted and there are no errors. Now let's try to add a parameter to the prettier config
VS Code

Let's go back to app.vue and restart ESLint server
VS Code
VS Code

And we get ESLint errors
VS Code

Also if you write npm run lint in the console, then errors will be displayed there too
Terminal

Now let's format the document again:
VS Code
VS Code
VS Code

Plugins in prettier

Only ESLint can be configured to adapt to prettier. The opposite is not possible. Keep in mind that prettier plugins are not related to ESLint in any way, and only ESLint can change depending on prettier. Plugins in prettier also start with prettier-plugin-, but the prefix cannot be omitted! Let's install the plugin - npm add -D prettier-plugin-tailwindcss. And connect it to prettierrc
VS Code

For this plugin to work we need to install tailwindcss in the project. Do it according to the guide. I already have another application where all this is connected, so don’t be alarmed that the name of the project has changed. Let's try to write the classes in the following order and run them through the linter
VS Code

As you can see, an error has arisen that we need to change the order of the classes and let's take advantage of the linter's hint and use the --fix flag
VS Code

And everything worked exactly the same as if we formatted using prettier, but it’s just more convenient to use in VSCode, and it will be more correct. But just know that you can format your files this way too. That is, here, using the eslint-plugin-prettier plugin and the eslint-config-prettier config, ESLint adapts to prettier and causes errors that come from it.

About prettier/prettier

prettier/prettier is exactly the rule that is defined in ESLint through prettier. For example, if you specified tabWidth: 5 in the .prettierrc.json file, then the ESLint configuration will throw a prettier/prettier error. And the most interesting thing is that it can also be configured, for example, replacing error with warn
VS Code
VS Code

Conclusion

Prettier and ESLint are very powerful tools that require at least a basic understanding to perform to their full potential. I also plan to write identical articles about these tools, since there is really very little information and even on native js it is difficult to intuitively deploy them. I hope this article helped you!

Top comments (6)

Collapse
 
pratik149 profile image
Pratik Rane

Thank you for explaining each step with the "why" behind it. Very rare to come across such detailed post!

It would have been nicer if you could have mentioned at the end how the final eslintrc.json, prettierrc.json and package.json files looked like, or may be an example git repo, if it is not too much ask for. 😄

Collapse
 
nikitadmitr profile image
Nikita • Edited

Appreciate it!

I've already deleted that tutorial project, but it might look like this

eslintrc.json

{
   "root": true,
   "extends": ["@nuxt", "plugin:prettier/recommended", "prettier"],
   "env": {
      "browser": true,
      "node": true
   }
}
Enter fullscreen mode Exit fullscreen mode

prettierc.json

{
   "endOfLine": "auto",
   "tabWidth": 3,
   "quoteProps": "consistent",
   "plugins": [
      "prettier-plugin-tailwindcss"
   ],
}
Enter fullscreen mode Exit fullscreen mode

package.json

{
   "name": "nuxt-app",
   "private": true,
   "type": "module",
   "scripts": {
      "build": "nuxt build",
      "dev": "nuxt dev",
      "generate": "nuxt generate",
      "preview": "nuxt preview",
      "postinstall": "nuxt prepare",
      "lint": "eslint .",
      "lint:fix": "eslint . --fix",
      "format": "prettier . --write"
   },
   "devDependencies": {
      "@nuxt/eslint-config": "^0.2.0",
      "@nuxtjs/eslint-module": "^4.1.0",
      "@nuxtjs/tailwindcss": "^6.11.2",
      "eslint": "^8.56.0",
      "eslint-config-prettier": "^9.1.0",
      "eslint-plugin-nuxt": "^4.0.0",
      "eslint-plugin-prettier": "^5.1.3",
      "nuxt": "^3.9.3",
      "prettier": "^3.2.4",
      "prettier-plugin-tailwindcss": "^0.5.11",
      "vue": "^3.4.14",
      "vue-router": "^4.2.5"
   }
}
Enter fullscreen mode Exit fullscreen mode

nuxt.config.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
   devtools: { enabled: true },
   modules: [
      "@nuxtjs/eslint-module"
   ]
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
llops profile image
dani llops

Super useful, thanks!!

Collapse
 
nurlan_tl profile image
Nurlan TL

Why I get:
admin@iMac myProject % npm run lint

lint
eslint .

Oops! Something went wrong! :(

ESLint: 8.57.0
No files matching the pattern "." were found.

It is fresh Nuxt installation, and all done as you say.

Collapse
 
nurlan_tl profile image
Nurlan TL

Fixed. Need to add .eslintrc.cjs:
module.exports = {
root: true,
extends: ["@nuxt/eslint-config"],
};

Collapse
 
nikitadmitr profile image
Nikita • Edited

Yeap, thank you. I've edited the comment