In daily project development, ESLint often plays a dispensable role. We want it to help us check our code, but we are afraid it will cause errors that can’t be handled. This article takes you deep into ESLint configuration and how it works.

This article was first published in the public number [front-end one read], more exciting content please pay attention to the latest news of the public number.

ESLint is a plug-in code detection tool, as described in its slogan:

Assembles JavaScript and JSX inspection tools

ESLint can not only detect JS, but also supports JSX and Vue, and its high extensibility allows it to support a wide range of projects.

The predecessors of ESLint

ESLint without mentioning its predecessors JSLint and JSHint, and the differences between them; The first is JSLint, developed by Douglas Crockford; JSLint was inspired by the C checker Lint. Lint was originally invented to scan C source files for errors, but as the language matured and compilers became better at finding problems, Lint tools were no longer needed.

JavaScript was originally invented just to do some simple work on the web (click events, form submission, etc.). With the development and improvement of JS language and the increase of project complexity, there was an urgent need for a validation tool to check JS syntax and other problems, so JSLint was born. It was the first syntactic checker for JS, open-source by Douglas Crockford in 2010. It does the same thing as Lint, scanning JS source files for errors; It also reads the file internally via fs.readfile and checks it line by line.

We can install jsLint globally, and then jsLint source.js checks our code; JSLint has certainly saved many JS developers a lot of time troubleshooting errors at first, but the problem with JSLint is obvious: all configuration items are built in unconfigurable, so if you use JSLint you have to follow Douglas Crockford’s own code style and specification; Add to that the fact that he is a big fan of the “don’t use” tradition, unlike developers who open up configurations or change rules as they see fit, and many people can’t stand his rules.

Anton Kovalyov developed JSHint based on JSLint because JSLint is intolerable to many people. JSHint was originally designed to allow developers to customize their own rules, thus providing a wealth of configuration options and giving developers great freedom; It also comes with a complete set of editor plugins, such as VIM, Sublime, Atom and Vs Code.

JSHint has always been open source and community-driven from the beginning, so it has grown quickly and has been used by some of the most familiar projects and companies: Facebook, Google, Jquery, Disqus, etc.

JSHint is configurable. You can put a. Jshintrc configuration file in your project, and JSLint will load a configuration file for code analysis, which will look like this:

{
    // Disallow unused variables
    "unused": true.// Disallow undefined variables
    "undef": true.// Ignore the end of the line without a semicolon
    "asi": true.// Global variables
    "globals": {
        "jQuery": true}}Copy the code

Since JSHint was developed based on JSLint, some of JSLint’s problems are inherited, such as being difficult to extend and to locate specific configuration rules based on errors. In 2013, Zakas realized that JSHint could not meet the needs of its own custom rules, so they envisioned developing an AST-based Linter that could dynamically execute additional rules, while also extending rules in a wide range of ways, and opened source the new ESLint in June 2013.

ESLint claims to be the next generation of JS Linter tools. Inspired by PHP Linter, ESLint parses source code into an AST and then checks whether the AST complies with the rules. ESLint initially parses source code into an AST using the Esprima parser. Then you can use arbitrary rules to check whether the AST meets expectations, which is why ESLint is so extensible.

JSHint’s position was not affected at first by the introduction of ESlint, because ESlint needed to convert source code to AST, whereas JSHint directly checks the source file strings and is therefore much slower than JSHint. What really enabled ESLint to implement corner overtaking was the advent of ES6.

When the ES6 specification was released in 2015, Babel was needed to convert code to ES5 or lower because most browsers did not support it well. ESLint can extend rules and replace the default parser. JSHint will not be fully supported in ES6. The Babel team developed babel-esLint for ESLint to replace the default parser esprima, making ESLint the first to support ES6.

configuration

ESLint is designed to be fully configurable, and we can configure its rules in a variety of ways, or configure the range of files to detect.

Initialize the

If you want to introduce ESLint in an existing project, you can initialize it in your project:

npm i eslint --save-dev
npx eslint --init
Copy the code

After a series of questions and answers, a familiar.eslintrc.js configuration file is created in the project root directory; After installation, you can use the command line to check the files in the project:

Check for a single file
npx eslint file1.js file2.js
Check SRC and scripts directories
npx eslint src scripts
Copy the code

Json we would normally configure the eslint command line to packes.json:

"scripts": {
    "lint": "npx eslint src scripts"."lint:fix": "npx eslint src scripts --fix"."lint:create": "npx eslint --init"
}
Copy the code

There is a –fix suffix here, ESLint provides automatic fixes for underlying errors. When we run Lint :fix, we find that some error messages have disappeared and the code has changed; However, it can only fix basic errors that don’t affect code logic, such as semicolons at the end of code, Spaces in expressions, and so on.

ESLint will only detect files with the.js suffix by default, but if we want to detect more types of files, such as.vue or.jsx, we can use the –ext option, separated by commas:

"scripts": {
    "lint": "npx eslint --ext .js,.jsx,.vue src",}Copy the code

Eslintignore tells ESLint to ignore specific directories or files:

public/
src/main.js
Copy the code

ESLint always ignores files in /node_modules/* and /bower_components/* except for files or directories specified in.eslintignore; Therefore, for some rules that can not be solved, but we need to package online, without affecting the operation, we can use the.eslintignore file to ignore it temporarily.

There are two ways to configure ESLint. The first way is to embed lint rules directly in source code;

/* eslint eqeqeq: "error" */
var num = 1
num == '1'
Copy the code

Eqeqeq represents the ESLint validation rule, and error represents the validation error level, as explained later. The ESLint validation rule will only apply to this file:

There are other comments we can use to more precisely manage esLint’s validation of a file or a line of code:

/* eslint-disable */
alert('This comment is placed at the top of the file, ESLint will not check the entire file')

/* eslint-enable */
alert('Re-enable ESLint checking')

/* eslint-disable eqeqeq */
alert('Only disallow one or more rules')

/* eslint-disable-next-line */
alert('Next line disallows ESLint checking')

alert('Current line disallows ESLint checking') // eslint-disable-line
Copy the code

Eslintrc.js is a configuration file, and there are several other configuration file names (priority from top to bottom) :

.eslintrc.js
.eslintrc.yaml
.eslintrc.yml
.eslintrc.json
.eslintrc
package.json
Copy the code

In general we use.eslintrc.js.

The configuration,

Let’s take a closer look at the configuration options inside the.eslintrc.js file:

module.exports = {
    "globals": {},
    "env": {
        "browser": true."es2021": true
    },
    "extends": "eslint:recommended"."parse": "babel-eslint"."parserOptions": {
        "ecmaVersion": 12."sourceType": "module"
    },
    "rules": {}};Copy the code

With globals, ESLint detects undeclared variables and issues errors, such as process in Node, console in browser, and $defined by jQuery via CDN. We can declare variables in globals:

{
    "globals": {
        // True indicates that the variable is read/write, false indicates that the variable is read-only
        "$": true."console": false}}Copy the code

However, node or the browser has a large number of global variables, which would be tedious to declare one by one, so we need to use our env, which is the default set of global variables defined by the environment:

{
    "env": {
        "browser": true."node": true."jquery": true}}Copy the code

For more environment parameters, see ESLint declaring the environment.

Then there are our parsers parse and parserOptions; As mentioned above, ESLint can change parsers. The “parse”: “babel-esLint” is used to specify which parser to use. It has the following options:

  • Esprima: The original parser used by ESLint
  • Espree: By default, a parser developed by ESLint itself based on Esprima V1.2.2
  • Babel-eslint: A wrapper around the Babel parser to make it compatible with ESLint.
  • @typescript-eslint/parser: Converts typescript to estree compatible form for use in ESLint.

So how do you choose among these parsers? If you want to use some advanced syntax (ES6789), use babel-esLint (requires NPM installation); If you want to use typescript, use @typescript-esLint /parser.

With the parser selected, we can pass some additional configuration parameters to the parser through parserOptions:

{
  "parser": "babel-eslint"."parserOptions": {
    // Code module type, optional script(default), module
    "sourceType": "module".// Es version number, default is 5, can use year 2015 (same as 6)
    "ecamVersion": 6.// Es feature configuration
    "ecmaFeatures": {
        "globalReturn": true.// Allow the use of return statements in the global scope
        "impliedStrict": true.// Enable strict mode globally
        "jsx": true / / enable JSX}}},Copy the code

The rules

ESLint can configure a large number of rules, and we can customize the required rules in the rules property of the configuration file:

{
    "rules": {// "semi": "off",
        "semi": 0.// "quotes": "warn",
        "quotes": 1.// "no-console": "error"
        "no-console": 2}}Copy the code

For inspection rules, there are three error levels:

  • “Off” or 0: turns off the rule
  • “Warn” or 1: Open rules, warn level errors (do not cause program exit)
  • “Error” or 2: enable rule, error level error (when triggered, the program will exit)

Some rules have no attributes and only need to be turned on or off. Some rules can pass attributes, so we pass parameters in arrays:

{
    "rules": {// Code indent, use TAB indent, switch statement case indent level, 1 means 2 Spaces
        "indent": ["error"."tab", { "SwitchCase": 1}].// double quotes
        "quotes": ["error"."double"].// Use semicolons at the end of statements
        "semi": ["error"."always"]}}Copy the code

For those of you who are new to ESLint, it must be confusing to see so many rules. Why should you memorize them one by one? Certainly not; The ESLint configuration file for the project was not created in one go, but was developed over the course of the project because not all of the rules were what we needed for the project. NPM run Lint so we can code first and use NPM run Lint to verify code specifications during coding. If an error is reported, we can use the error message to check which specification is reported in detail:

For example, the error no-unused-vars is generated in line 6. It is found that we have a variable defined in js but not used. This specification can be further determined after team consultation to determine whether the project needs it.

extension

If it is tedious to negotiate configuration for every rule, we can use some mature and universally followed coding specifications (best practices) at the beginning of the project configuration. We can pass in some specifications via the extends field, which accepts String/Array:

{
    "extends": [
        "eslint:recommended"."plugin:vue/essential"."@vue/prettier"."eslint-config-standard"]}Copy the code

Extends can use one of the following types of extensions:

  • Eslint: Official extension to esLint starting with two:eslint:recommended(Recommended specifications) andeslint:all(All specifications).
  • Plugin: The extension that starts is a plug-in type extension
  • Eslint-config: the beginning is from the NPM package and can be omitted when usedeslint-config-For example, the top one can be written asstandard
  • The @ : extension, like eslint-config, adds a layer of scope on top of the NPM package

Note that multiple extensions have the same rule. Use the rule in the extension introduced later.

Eslint :recommended rules Are marked with a green √ on the right side of the rule list.

Plug-in type extensions are usually installed through NPM. For example, vUE above, let’s install the plug-in first:

npm install --save-dev eslint eslint-plugin-vue
Copy the code

There are many similar types of extensions to choose from after you install the plugin. For example, Vue has the following extensions:

  • The plugin: vue/base: the base
  • Plugin :vue/essential
  • Plugin :vue/recommended
  • Plugin :vue/strongly-recommended

For rules in the extension, we can also override it with rules:

{
  "extends": [
    "plugin:vue/recommended"]."rules": {
    // Override rule
    "vue/no-unused-vars": "error"}}Copy the code

In addition to the eslint-config-standard above, there are several more well-known coding specifications:

However, it is important to note that many specifications require not only the extension itself, but also plug-ins, such as eslint-config-standard. We also need the following plug-ins to be effective:

npm i eslint-config-standard -D
npm i eslint-plugin-promise eslint-plugin-import eslint-plugin-node -D
Copy the code

The plug-in

In Webpack, plugins are used to extend functionality to handle more file types and functions, and plugins in ESLint do the same; While ESLint has hundreds of rules to choose from, with the development of JS frameworks and syntax, this is not enough, because official rules can only check standard JS syntax; ESLint would not be able to detect if we were writing vUE or React JSX.

In this case, you need to install the ESLint plugin, which can be used to customize some special rules for detection; Eslint plugins start with eslint-plugin- and can be omitted when used. For example, we used the eslint-plugin-vue plugin to check.vue files above; Note that if only “plugins”: [“vue”] were configured for eslint-plugin-vue, the template content in the vue file would still fail parsing.

This is because neither the default espree nor the babel-esLint parser can parse the contents of template in.vue; The eslint-plugin-vue plugin relies on the vue-eslint-parser. The Vue-eslint-parser only parses template content and does not detect JAVASCRIPT content in script tags, so we also need to specify the following parser:

{
    "extends": ["eslint:recommended"]."plugins": ["vue"]."parser": "vue-eslint-parser"."parserOptions": {
        "parser": "babel-eslint"."ecmaVersion": 12."sourceType": "module",}}Copy the code

Parseroptions. parser can only have one outer parser. We can’t write another one if we use vue-eslint-parser. So what vue-eslint-Parser does is pass in a parser option to handle the JS content of script.

If you want ESLint to detect vue files, be sure to add the. Vue suffix to the –ext option.

Install the react plugin and select the corresponding extension rule:

{
    "extends": [
        "eslint:recommended"."plugin:react/recommended"]."parserOptions": {
        // Enable JSX syntax support
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12."sourceType": "module"
    },
    "plugins": [
        "react"],}Copy the code

Cooperate with the prettier

While ESLint does some checking on our code formatting (semicolons, double quotes, etc.), it doesn’t always have a uniform code style, we still need a tool Prettier; 1. What is Prettier? Prettier, a code formatting tool that supports many languages, is described as “opinionated” by its website, which translates as opinionated.

Prettier also has four characteristics:

  • An opinionated code formatter
  • Supports many languages
  • Integrates with most editors
  • Has few options

So why does Prettier use opinionated? Each team member may use a different editor or plug-in, and each plug-in will have its own formatting specification, which leads to great inconsistency in code style during development, and even unnecessary conflicts. Prettier told us to define style, as it does (doesn’t it look like JSLint); But not completely closed, open some necessary Settings, this is also the last few options meaning; So Prettier just had to beautify the code.

Prettier’s three packages are used for installing the necessary plugins:

npm i prettier 
      eslint-plugin-prettier 
      eslint-config-prettier
Copy the code

The first is the eslint-plugin-Prettier plug-in, which calls Prettier to check your code style by formatting your code using Prettier and comparing it with the code before formatting. The place would be marked by Prettier.

Prettier is marked, but there is no warning when Prettier is marked, so we need to add the following configuration in rules:

{
    "plugins": ["prettier"]."rules": {
        "prettier/prettier": "error",}}Copy the code

If you do not want Prettier to affect project packaging, you could also change Prettier’s error from Error to WARN

With ESLint’s auto-fix –fix, we can fix this simple style problem; What if we want to customize some styles? 3, Although Prettier is an opinionated tool, Prettier also opens up configurations for us to customize, creating a new prettierrc.json file in a project:

{
  / / stern commas
  "trailingComma": "es5".// Indent length
  "tabWidth": 4.// End-of-code semicolon
  "semi": false./ / single quotation marks
  "singleQuote": true.// Maximum length of a single line of code
  "printWidth": 100.// Parentheses for object literals
  "bracketSpacing": true.// Arrow function arguments are parenthesized
  "arrowParens": "always",}Copy the code

Here are some common ones, and we can find more configuration rules in the option configuration website.

This configuration fixes the code, but if we come across another stubborn extension, such as the eslint-config-standard extension, it has its own code style; If you format Prettier, standard doesn’t work. Prettier says wrong if Prettier is fixed by Standard, there are two Prettier girls on both sides

Prettier already does this for us by adding eslint-config-prettier at the end of extends using the last property of extends that covers the previous extension, we can turn off some rules relating to Prettier:

{
    "extends": ["standard"."prettier"]."plugins": ["prettier"]."rules": {
        "prettier/prettier": "error",}}Copy the code

Eslint – plugin – prettier plugin also comes with the plugin: prettier/it extend configuration, can enable the plug-ins and eslint – config – at the same time expanding prettier, So we can just configure recommended:

{
    "extends": ["standard"."plugin:prettier/recommended"]."rules": {
        "prettier/prettier": "error",}}Copy the code

To support Prettier, eslint-plugin-prettier is integrated with eslint-config-prettier in Vue, Node_modules /@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules/@vue/eslint-config-prettier node_modules

module.exports = {
  plugins: ['prettier'].extends: [
    require.resolve('eslint-config-prettier'),
    require.resolve('eslint-config-prettier/vue')].rules: {
    'prettier/prettier': 'warn'}}Copy the code

For more front-end information, please pay attention to the public number [front-end reading].

If you think it’s good, check out my Nuggets page. Please visit Xie xiaofei’s blog for more articles