• 浅析ESlint的作用、演进历史、ESLint校验文件方式及常见配置介绍、2种配置方式、eslint检测配置文件的机制


    一、为什么要用ESLint

    1、总结为两点:保持代码风格一致、减少代码出错几率

      为了解决这类静态代码问题,每个团队都需要一个统一的 JS 代码规范,团队成员都遵守这份代码规范来编写代码。当然,靠人来保障代码规范是不可靠的,需要有对应的工具来保障,ESLint 就是这个工具

    2、为什么不是Prettier

      Prettier确实可以按照设置的规则对代码进行统一格式化,但是需要明确的一点是,Prettier只会在格式上对代码进行格式化,一些隐藏的代码质量问题Prettier是无法发现的,而ESLint可以。

    3、目标:开发时提示、保存时自动修复、提交时检测

    二、ESlint 演进历史

      提到ESLint,我们就不得不提及他的前辈们JSLint和JSHint,以及它们的区别。

    1、JSLint:

      JSLint 的灵感来源于C语言的检查工具 Lint,用来扫描C语言源文件以便找到其中的错误。

      JSlint 是在2010年开源的第一款针对JS的语法检测工具,它和Lint做着相同的事,扫描JS的源文件来找到错误;它内部也是通过fs.readFile来读取文件然后逐行来进行检查

      JSLint的问题很明显:所有的配置项都内置不可配置,本身推崇爱用不用的传统,不像开发者开放配置或者修改他觉得对的规则,因此很多人也无法忍受他的规则

    2、JSHint,它的初衷就是为了能让开发者自定义规则 lint rules,因此提供了丰富的配置项,给开发者极大的自由

      JSHint相比于JSLint,最大的特点就是可配置,我们可以在项目中放入一个.jshintrc的配置文件,JSLint就会加载配置文件用于代码分析

      由于JSHint是基于JSLint开发的,因此JSLint的一些问题也继承下来了,比如不易扩展以及不容易直接根据报错定位到具体的配置规则等

    3、ESLint

      2013年 Zakas 大佬发现JSHint无法满足自己定制化规则的需要,因此设想开发一个基于AST的Linter,可以动态执行额外的规则,同时可以很方面的扩展规则,于是在13年6月份开源推出了全新的ESLint。

      灵感来源于PHP Linter,将源码解析成AST,然后检测AST是否符合规则;ESLint最开始使用esprima解析器将源码解析成AST,然后就可以使用任意规则来检测AST是否符合预期,这也是ESLint高可扩展的原因。

      刚开始ESlint的推出并没有撼动JSHint的霸主地位,由于ESlint需要将源码转为AST,而JSHint直接检测源文件字符串,因此执行速度比JSHint慢很多;真正让ESLint实现弯道超车的是ES6的出现

      2015年,ES6规范发布后,由于大部分浏览器支持程度不高,因此需要Babel将代码转换编译成ES5或者更低版本;同时由于ES6变化很大,短期内JSHint无法完全支持,这时ESLint的高扩展性的优点显现出来了,不仅可以扩展规则,连默认的解析器也能替换;Babel团队就为ESLint开发了babel-eslint替换默认的解析器esprima,让ESLint率先支持ES6。

    三、ESLint 配置

      ESLint被设计成完全可配置的,我们可以用多种方式配置它的规则,或者配置要检测文件的范围。

    1、初始化:如果想在现有的项目中引入eslint,我们可以在项目中进行初始化:

    npm i eslint --save-dev
    npx eslint --init

      在经过一系列问答后,会在项目根目录创建一个我们熟悉的.eslintrc.js配置文件;安装后就可以通过命令行对项目中的文件需要检测了:

    # 检测单个文件
    npx eslint file1.js file2.js
    # 检测src和scripts目录
    npx eslint src scripts

      一般我们会把eslint命令行配置到packages.json中:

    "scripts": {
        "lint": "npx eslint src scripts",
        "lint:fix": "npx eslint src scripts --fix",
        "lint:create": "npx eslint --init"
    }

      这里有一个--fix后缀,是ESLint提供自动修复基础错误的功能,我们运行lint:fix后发现有一些报错信息消失了,代码也改变了;不过它只能修复一些基础的不影响代码逻辑的错误,比如代码末尾加上分号、表达式的空格等等。

      ESLint默认只会检测.js后缀的文件,如果我们想对更多类型的文件进行检测,比如.vue、.jsx,可以使用--ext选项,参数用逗号分隔:

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

      对于一些公共的js,或者测试脚本,不需要进行检测,我们可以通过在项目根目录创建一个.eslintignore告诉ESLint去忽略特定的目录或者文件:

    public/
    src/main.js

      除了.eslintignore中指定的文件或目录,ESLint总是忽略/node_modules/* 和/bower_components/*中的文件;因此对于一些目前解决不了的规则报错,但是我们需要打包上线,在不影响运行的情况下,我们就可以利用.eslintignore文件将其暂时忽略。

    2、ESLint一共有两种配置方式

    • 配置注释:使用JavaScript注释把配置信息直接嵌入到一个代码源文件中
    • 配置文件:1. 使用 JavaScript、JSON 或者 YAML 文件为整个目录(处理你的主目录)和它的子目录指定配置信息。可以配置一个独立的 .eslintrc.* 文件,或者直接在 package.json 文件里的 eslintConfig 字段指定配置,ESLint 会查找和自动读取它们,再者,你可以在命令行运行时指定一个任意的配置文件。

    (1)第一种方式是直接把lint规则嵌入源代码中;

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

      eqeqeq代表eslint校验规则,error代表校验报错级别,后面会详细说明;这个eslint校验规则只会对该文件生效

      我们还可以使用其他注释,更精确地管理eslint对某个文件或某一行代码的校验:

    /* eslint-disable */
    alert('该注释放在文件顶部,eslint不会检查整个文件')
    /* eslint-enable */
    alert('重新启用eslint检查')
    /* eslint-disable eqeqeq */
    alert('只禁止某一个或多个规则')
    /* eslint-disable-next-line */
    alert('下一行禁止eslint检查')
    alert('当前行禁止eslint检查') // eslint-disable-line

    (2)第二种方式是直接把lint规则放到我们的配置文件中,

      上面init初始化生成的.eslintrc.js就是一个配置文件,官方还提供了其他几种配置文件名称(优先级从上到下),一般情况下我们使用.eslintrc.js就可以了。

    .eslintrc.js
    .eslintrc.yaml
    .eslintrc.yml
    .eslintrc.json
    .eslintrc
    package.json

    四、配置详解

    // 我们详细看下.eslintrc.js文件内部有哪些配置选项:
    module.exports = {
        "globals": {},
        "env": {
            "browser": true,
            "es2021": true
        },
        "extends": "eslint:recommended",
        "parse": "babel-eslint",
        "parserOptions": {
            "ecmaVersion": 12,
            "sourceType": "module"
        },
        "rules": {}
    };

    1、globals 全局变量:脚本在执行期间访问的额外的全局变量

    当访问当前源文件内未定义的变量时,no-undef 规则将发出警告。如果你想在一个源文件里使用全局变量,在Globals中定义这些全局变量,这样ESLint就不会发出警告了

      首先是我们的 globals ,ESLint会检测未声明的变量,并发出报错,比如node环境中的process,浏览器环境下的全局变量console,以及我们通过cdn引入的jQuery定义的$等;我们可以在 globals 中进行变量声明:

    {
        "globals": {
            // true表示该变量可读写,false表示变量是只读
            "$": true,
            "console": false
        }
    }

    2、env 环境

      但是node或者浏览器中的全局变量很多,如果我们一个个进行声明显得繁琐,因此就需要用到我们的 env,这是对环境定义的一组全局变量的预设:一个环境定义了一组预定义的全局变量

    指定不同的环境可以给对应环境下提供预设的全局变量,比如说在 browser 环境下,可以使用 window 全局变量;在 node 环境下,可以使用 process 全局变量等。

    这些环境并不是互斥的,所以可以同时定义多个。可以在源文件里、在配置文件中或使用 命令行 的 --env 选项来指定环境。

    {
        "env": {
            "browser": true,
            "node": true,
            "jquery": true
        }
    }

      更多的环境参数可以看ESLint声明环境。

    3、parser解析器及解析参数parserOptions

    这里可以类比webpack,自身只能处理js、及json文件,css、html等文件需要通过自定义loader处理来理解

      解析器将源代码转换为称为抽象语法树AST的数据格式,然后,插件使用这种数据格式围绕代码的外观或行为创建称为lint规则的断言。

      我们上面说到ESLint可以更换解析器,"parse": "babel-eslint"就是用来指定要使用的解析器,它有以下几个选择:

    • esprima:ESLint最开始使用的解析器
    • espree:默认,ESLint自己基于esprima v1.2.2开发的一个解析器
    • babel-eslint:一个对Babel解析器的包装,使其能够与ESLint兼容。
    • @typescript-eslint/parser:将TypeScript转换成与estree兼容的形式,以便在ESLint中使用。

      那么这几个解析器怎么选择呢?如果你想使用一些先进的语法(ES6789),就使用babel-eslint(需要npm安装);如果你想使用typescript,就使用@typescript-eslint/parser。

      选好了解析器,我们可以通过parserOptions给解析器传入一些其他的配置参数:

    {
      "parser": "babel-eslint",
      "parserOptions": {
        // 代码模块类型,可选script(默认),module
        "sourceType": "module",
        // es版本号,默认为5,可以使用年份2015(同6)
        "ecamVersion": 6,
        // es 特性配置
        "ecmaFeatures": {
            "globalReturn": true, // 允许在全局作用域下使用 return 语句
            "impliedStrict": true, // 启用全局 strict mode 
            "jsx": true // 启用 JSX
        }
      },
    }

    4、规则 rules

      ESLint可以配置大量的规则,我们可以在配置文件的rules属性自定义需要的规则:

      对于检验规则,有3个报错等级:

    • "off" 或 0:关闭规则
    • "warn" 或 1:开启规则,warn级别的错误 (不会导致程序退出)
    • "error" 或 2:开启规则,error级别的错误(当被触发的时候,程序会退出)

      有些规则没有属性,只需控制开启还是关闭;有些规则可以传入属性,我们通过数组的方式传入参数:

    {
        "rules":{
            // 代码缩进,使用tab缩进,switch语句的case缩进级别,1表示2个空格
            "indent": ["error", "tab", { "SwitchCase": 1 }],
            // 引号,双引号
            "quotes": ["error", "double"],
            // 在语句末尾使用分号
            "semi": ["error", "always"]
        }
    }

      对于刚接触ESLint的同学,看到这么多的规则肯定很懵逼,难道要一条一条来记么?肯定不是的;项目的ESLint配置文件并不是一次性完成的,而是在项目开发中慢慢完善起来的,因为并不是所有的规则都是我们项目所需要的。因此我们可以先进行编码,在编码的过程中使用npm run lint校验代码规范,如果报错,可以通过报错信息去详细查看是那一条规范报错:

      比如这里的报错no-unused-vars我们可以看到它来自第六行,再去文档查找,发现是我们在js中有一个定义了却未使用的变量;在团队协商后可以进一步来确定项目是否需要这条规范。

    5、扩展 extends

      如果每条规则都需要团队协商配置还是比较繁琐的,在项目开始配置时,我们可以先使用一些业内已经成熟的、大家普遍遵循的编码规范(最佳实践);我们可以通过extends字段传入一些规范,它接收String/Array:

    {
        "extends": [
            "eslint:recommended",
            "plugin:vue/essential",
            "@vue/prettier",
            "eslint-config-standard"
        ]
    }

      extends可以使用以下几种类型的扩展:

    • eslint:开头的ESLint官方扩展,有两个:eslint:recommended(推荐规范)和eslint:all(所有规范)。
    • plugin:开头的扩展是插件类型扩展
    • eslint-config:开头的来自npm包,使用时可以省略eslint-config-,比如上面的可以直接写成standard
    • @:开头的扩展和eslint-config一样,是在npm包上面加了一层作用域scope

      需要注意的是:多个扩展中有相同的规则,以后面引入的扩展中规则为准。

      eslint:recommended推荐使用的规则在规则列表的右侧用绿色√标记。

      插件类型的扩展一般先通过npm安装插件,以上面的vue为例,我们先来安装:npm install --save-dev eslint eslint-plugin-vue

      安装后一个插件中会有很多同类型扩展可供选择,比如vue就有以下几种扩展:

    • plugin:vue/base:基础
    • plugin:vue/essential:必不可少的
    • plugin:vue/recommended:推荐的
    • plugin:vue/strongly-recommended:强烈推荐

      针对扩展中的规则,我们也能够通过rules来对它进行覆写

    {
      "extends": [
        "plugin:vue/recommended"
      ],
      "rules": {
        // 覆写规则
        "vue/no-unused-vars": "error"
      }
    }

      除了上面的eslint-config-standard,还有以下几个比较知名的编码规范:

      不过需要注意的是,很多规范不仅需要安装扩展本身,还需要配合插件,比如eslint-config-standard,我们还需要安装下面几个插件才能有效:

    npm i eslint-config-standard -D
    npm i eslint-plugin-promise eslint-plugin-import eslint-plugin-node -D

    6、插件 plugins

    ESLint虽然可以定义很多的rules,以及通过extends来引入更多的规则,但是说到底只是检查JS语法。如果需要检查Vue中的template或者React中的jsx,就束手无策了。所以引入插件的目的就是为了增强ESLint的检查能力和范围。

    在配置文件里配置插件时,可以使用 plugins 关键字来存放插件名字的列表。插件名称可以省略 eslint-plugin- 前缀。

      在Webpack中,插件是用来扩展功能,让其能够处理更多的文件类型以及功能,ESLint中的插件也是同样的作用;虽然ESLint提供了几百种规则可供选择,但是随着JS框架和语法的发展,这么多规则还是显得不够,因为官方的规则只能检查标准的JS语法;如果我们写的是vue或者react的jsx,那么ESLint就不能检测了。

      这时就需要安装ESLint插件,用来定制一些特色的规则进行检测;eslint插件以eslint-plugin-开头,使用时可以省略;比如我们上面检测.vue文件就用到eslint-plugin-vue插件;需要注意的是,我们在配置eslint-plugin-vue这个插件时,如果仅配置"plugins": ["vue"],vue文件中template内容还是会解析失败。

      这是因为不管是默认的espree还是babel-eslint解析器都无法解析.vue中template的内容;eslint-plugin-vue插件依赖vue-eslint-parser解析器,而vue-eslint-parser解析器只会解析template内容,不会检测script中的JS内容,因此我们还需要指定一下解析器:

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

      上面parserOptions.parser不少同学肯定看的有点迷糊,这是由于外层的解析器只能有一个,我们已经用了vue-eslint-parser就不能再写其他的;因此vue-eslint-parser的做法是在解析器选项中再传入一个解析器选项用来处理script中的JS内容。

      如果想让ESLint检测vue文件,确保将.vue后缀加入--ext选项中。

    // 而react配置则较为简单了,引入插件,选择对应的扩展规则即可:
    {
        "extends": [
            "eslint:recommended",
            "plugin:react/recommended"
        ],
        "parserOptions": {
            // 启用jsx语法支持
            "ecmaFeatures": {
                "jsx": true
            },
            "ecmaVersion": 12,
            "sourceType": "module"
        },
        "plugins": [
            "react"
        ],
    }

    7、其他配置:配置当前目录为 root

      ESLint检测配置文件步骤:

    1. 在要检测的文件同一目录里寻找 .eslintrc.*package.json
    2. 紧接着在父级目录里寻找,一直到文件系统的根目录;
    3. 如果在前两步发现有 root:true 的配置,停止在父级目录中寻找 .eslintrc
    4. 如果以上步骤都没有找到,则回退到用户主目录 ~/.eslintrc 中自定义的默认配置;
      通常我们都习惯把 ESLint 配置文件放到项目根目录,因此可以为了避免 ESLint 校验的时候往父级目录查找配置文件,所以需要在配置文件中加上 root: true。
    {
        "root": true,
    }

    五、ESLint 校验文件

    1、校验.js类型文件
    // 校验 a.js 和 b.js 
    npx eslint a.js b.js 
    // 校验 src 和 scripts 目录 
    npx eslint src scripts

    2、校验其他类型文件

      通常ESLint只能校验JS文件。比如需要校验.vue文件,光配置vue插件vue-eslint-parser解析器是不够的,还需要让ESLint在查找文件的时候找到.vue文件。ESLint提供了--ext来指定具体需要校验的文件

    npx eslint --ext .js,.vue src

    3、自动修复部分校验错误的代码

      rules列表项 中标识了规则表示该规则是可以自动修复的,ESLint提供了--fix

    // package.json配置scripts
    { 
        "scripts": { 
            "lint": "npx eslint --ext .js,.vue src", 
            "lint:fix": "npx eslint --fix --ext .js,.vue src", 
        } 
    }

    4、过滤一些不需要校验的文件:通过创建一个.eslintignore文件来配置,告诉 ESLint 校验的时候忽略它们

    学习链接:https://mp.weixin.qq.com/s/Gg37sEBsu3J5Ov6a8Frq5w

  • 相关阅读:
    音频处理之回声消除及调试经验
    音频软件开发中的debug方法和工具
    ZJOI2015地震后的幻想乡
    HEOI2015小L的白日梦
    THUWC2017随机二分图
    PKUWC Slay The Spire
    dp的一些计划
    鸡汤征集贴
    弱菜的各种模板
    洛谷P4902乘积
  • 原文地址:https://www.cnblogs.com/goloving/p/16171055.html
Copyright © 2020-2023  润新知