前端工程化之eslint代码检查

2,120 阅读10分钟

前言

为什么要进行代码质量检查呢,原因有三:

  1. 一些常见代码问题,如果在编译或运行时不能及时发现,代码中的语法问题会直接导致编译或运行时错误,影响开发效率和代码质量;
  2. 统一代码习惯,每一个团队或个人都会有一些代码规范或者代码习惯,为了便于后期维护和阅读,我们编写的代码也需要符合一定的格式规范:
    • 空格;
    • 统一缩进;
    • 命名规范;
  3. 保证线上代码质量。在版本管理中,我们需要在提交或发布之前自动执行一些代码检查工作,确保我们的代码符合最终版本要求。

前端代码中的常见问题

书写风格

简单来说,太过随意的代码会让开发者难以阅读,而难以阅读的代码有时甚至不如推倒重来。

// bad
var once
    , upop
    , aTime;

// good
var once,
   upon,
   aTime;
   
// bad
var hero = {
   firstName: 'Bob'
   , lastName: 'parr'
   , heroName: 'Mr.Incredible'
   , superPower: 'strength'
};

// good
var hero = {
   firstName: 'Bob',
   lastName: 'parr',
   heroName: 'Mr.Incredible',
   superPower: 'strength'
};

代码规范

不遵守编码标准和惯例的代码会让你看一眼就不想继续看、甚至看半天而不知所云。有人认为初级程序员才会有这种问题,其实不然,一些工作经验两三年的同学写的代码依然如此。对于一些个人自学意识不够积极、没有团队规范性指引的程序员,很容易出现代码格式不规范的问题。

Lint 会通过源代码去查找:

  • 格式问题;
  • 不遵守编码标准和惯例;
  • 精确定位程序中的可能存在的逻辑错误。

代码 Lint 是动态的监测代码边写的错误,以便我们能写出高质量的代码。
要与 Prettier 或者 Format 要区别开来,Lint 只会告诉你代码中的错误或者不规范的地方,而 Format 是用来对格式进行调整的。

ESlint 介绍

ESlint 是 JavaScript 的 linting 实用程序。

ESlint 不依赖与特定的编码约定,用户也可以自由地启用或禁用各个编码约定。从这个意义上讲,它的一个主要特点是其高度可定制性。

用户可以通过定义原始规则来灵活的设置编码标准,这些规则是 Elint 中默认可用的编码规则。

核心概念

  • 配置文件:
    .eslintrc,.eslintrc.js,.eslintrc.yml

  • Rules:

    • "off"或0:关闭规则;
    • "wran"或1:开启规则,使用警告级别的错误:warn(不会导致程序退出);
    • "error"或2:开启规则,使用错误级别的错误:error(当贝触发的时候,程序会退出)。 看一个例子:
    {
        "rules":{
            "semi":["error","never"],
            "quotes":["error","single"]
        }
    }
    

    看一个例子:

    {
        "rules":{
            "semi":["2","never"],
            "quotes":["2","single"]
        }
    }
    
  • Extends:
    使用别人提供的包,如 Google:

    {
        "extends""google"
    }
    
  • Plugins:
    ESlint 提供的默认规则涵盖了基本规则,但 JavaScript 可以 使用的范围非常广泛。因此,您可能希望规则不在默认规则中。这种情况下,可以在 ESlint 中开发自己的独立规则。为了让第三方开发自己的规则,ESlint 允许使用插件,如果你在 npm 中搜索 eslint-plugin-*,你可以找到第三方提供的大量自定义插件。如果 ESlint 的默认规则未提供要使用的规则,则建议您查找插件。

    与可共享配置类似,它很容易设置。例如,如果要对 React 代码进行静态分析,可以安装名为 eslint-plugin-react 的插件,并使用以下设置来执行 React 语法特有的静态分析。

    {
        "extends""google",
        "plugins": ["react"],
        "rules":{
            "semi":[2,"never"],
            "quotes":[2,"single"]
        }     
    }
    

起步与安装

在项目中使用

// --dev 会把 eslint 安装到package.json 文件中的 devDependencies 属性中,意思是知识开发阶段用到这个包,上线时就不需要这个包了
yarn add eslint --dev

新增 package.json 脚本:

  "scripts": {
   "lint": "eslint app.js",
   "lint:create": "eslint --init"
   },

然后使用 run 命令:

yarn lint:create

在全局使用

yarn global add eslint
eslint --init

image.png

生成的 .eslintrc.js 文件导出一个对象,对象包含属性 env、extends、parserOptions、plugins、rules 五个属性:

  • env:指定脚本的运行环境。每种环境都有一组特定的预定义全局变量,(如:nodejs,browser,commonjs 等)中。
  • parserOptions:用于指定想要支持的 JavaScript 语言选项:
    • ecmaVersion:默认设置为3,5(默认),你可以使用6、7、8或9来指定你想要使用的 ECMAScript 版本。你也可以用使用年份命名的版本号指定为2015(同6),2016(同7),或2017(同8)或2018(同9);
    • sourceType:设置为 "script"(默认)或"module"(如果你的代码是 ECMAScript)。
  • globals:执行代码时脚本需要访问的额外全局变量;
  • rules:开启某些规则,也可以设置规则的等级。

.eslintignore

可以在项目根目录创建,告诉 ESlint 忽略某些文件或者目录。相当于 .gitignore 都是纯文本文件。

image.png

ESlint 的使用方法

在你根据以上步骤设置 .eslintrc.js 配置文件后,你可以在项目更目录运行 ESlint,检查你的 js 文件:

yarn lint index.js

vscode 使用 eslint 保存自动格式化

  1. 在项目跟目录添加.eslintrc.js 文件

    // https://cn.eslint.org/docs/rules/
    // 
    /*
    * "off"或者0,不启用这个规则
    * "warn"或者1,出现问题会有警告
    * "error"或者2,出现问题会报错
    */
    
    module.exports = {
         root: true, //此项是用来告诉eslint找当前配置文件不能往父级查找
         env: { //环配置 如 "browser": true, node: true,
           node: true,
         },
         extends: [
           'google',
         ],
         rules: {
           'array-callback-return': 1, //return 后面是否允许省略
           "arrow-parens": ["error", "as-needed"], // 箭头函数的参数可以不使用圆括号
           'consistent-return': 0, //要求 return 语句要么总是指定返回的值,要么不指定
           'camelcase': 0, //强制驼峰法命名
           'eqeqeq': 0, //强制全等( === 和 !==)
           'func-names': 0, //函数表达式必须有名字
           "global-require": 0, // 取消对require的验证,使得可以使用require来加载图片的相对路径
           "import/no-unresolved": 0, // 取消自动解析路径,以此开启alias的别名路径设置
           'import/extensions': 0, // 取消对文件扩展名的验证
           'indent': 'off', //缩进风格(强制使用一致的缩进)
           "linebreak-style": 0, // 取消换行符\n或\r\n的验证()
           'max-len': 0, //字符串最大长度
           "no-unused-vars": 1, //禁止出现未使用过的变量
           "no-redeclare": 1, //禁止多次声明同一变量
           'no-use-before-define': 1, //禁止在变量定义之前使用它们
           "no-unused-expressions": 0, // 允许使用未使用过的表达式,以此来支持a && a()的代码形式
           'no-restricted-syntax': 1, //禁用特定的语法
           'no-plusplus': 1, //禁止使用++,--
           'no-underscore-dangle': 0, // 允许在标识符中使用下划线
           'no-param-reassign': 0, // 禁止对 function 的参数进行重新赋值
           'no-nested-ternary': 0, // 禁止嵌套三元表达式
           'no-else-return': 0, //禁止 if 语句中 return 语句之后有 else 块
           'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
           'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
           'no-shadow': [1, { //外部作用域中的变量不能与它所包含的作用域中的变量或参数同名
             "allow": ["resolve", "reject", "done", "cb"]
           }],
           'prefer-rest-params': 1, //要求使用剩余参数而不是 arguments
           'prefer-arrow-callback': 0, //要求回调函数使用箭头函数
           'prefer-const': 1, //首选const
           "semi": false, // 使用分号, 默认true
           "singleQuote": true, // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
           "tabWidth": 4, // tab缩进大小,默认为4
           'template-curly-spacing': 'off', //要求或禁止模板字符串中的嵌入表达式周围空格的使用
         },
         parserOptions: {
           parser: 'babel-eslint',
         },
       };
    
  2. 在vscode中添加 eslint。

    image.png

  3. 配置保存时按eslint规则自动格式化。
    可在“首选项”--“设置”中找到settings.json

    image.png

    添加如下配置:

    ```JavaScript
    "editor.codeActionsOnSave": {
         "source.fixAll.eslint": true
    },
    "eslint.format.enable": true
    ```
    

    可以看下eslint的详细说明,有如图的配置说明,就使用新版本的配置:

    image.png

    这样配置完成后保存文件时就会自动格式化了。

Vue 项目中使用 ESLint 和 Prettier

虽然ESLint会对我们的代码格式进行一些检测(比如分号、单双引号等),但是并不能完全统一代码风格,我们还需要一个工具Prettier。它并不关心你的语法是否正确,只关心你的代码格式,比如是否使用单引号,语句结尾是否使用分号等等,不仅可以用来检测 JavaScript 代码格式,还可以检测 vue 文件,react 文件。

深入 VSCode 配置

大部分的同学开启了插件以后,VSCode 仍然没有高亮。因为需要对 VSCode 中的相关参数继续配置。

"eslint.probe": [
   "javascript",
   "javascriptreact",
   "typescript",
   "typescriptreact",
   "html",
   "vue",
   "markdown"
],

eslint.probe 这个规定 ESlint 插件需要校验的语言类型,添加上对应的语言后 VSCode 才会在代码编辑器中正确的高亮错误的语法,并且会在窗口中输出错误信息。如果开发 vue 的同学需要在这里添加上 ["html", "vue"] 这样才会在 .vue 单文件中开启 ESlint 检测,这两个选项需要 eslint-plugin-vue eslint-plugin-html两个包支持,需要安装到项目中。

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","html"],
    "parser": "vue-eslint-parser",
    "parserOptions": {
        "parser": "babel-eslint",
        "ecmaVersion": 12,
        "sourceType": "module",
    },
}

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

开启 prettier 格式化

开启上面的选项后,VSCode 已经能正确的显示 ESlint 的报错信息,接下来要开启 prttier 的格式化。前面有说到,prettier 是一个校验代码格式化的工具,而 ESlint 的是校验语法的工具。一个项目维护两种配置可能有些麻烦,因此 ESlint 直接以插件的形式提供了支持。

安装

要使用Prettier当然先得安装它,然后还需要安装 eslint-plugin-prettier

为了防止PrettierESLint格式化功能冲突,还需要安装 eslint-config-prettier 来关闭ESLint中的代码格式化功能。

yarn add -D eslint
yarn add -D eslint-plugin-prettier
yarn add -D eslint-config-prettier

在 .prettierignore 和 .eslintignore 文件中可以添加那些不需要格式化的文件或文件夹,在美化代码挑bug时忽略这些文件。

配置

下面来看看在ESLint中添加Prettier插件的配置文件是什么样子的:

{
  plugins: ["prettier"],
  rules: {
    prettier/prettier: "error"
  }
}

eslint-plugin-prettier 的GitHub上给出了一种推荐配置:

{
  extends: ["plugin:prettier/recommended"]
}

我们可以在项目中新建一个.prettierrc.json文件:

{
     // 尾逗号
     "trailingComma": "es5",
     // 缩进长度
     "tabWidth": 4,
     // 代码末尾分号
     "semi": false,
     // 单引号
     "singleQuote": true,
     // 单行代码最大长度
     "printWidth": 100,
     // 对象字面量的括号
     "bracketSpacing": true,
     // 箭头函数参数加括号
     "arrowParens": "always",
}

这里简单贴一些常用的,我们可以在官网选项配置找到更多的配置规则。

这样配置后虽然能修复代码了,但是如果遇到另一个也固执己见的扩展,比如我们引入eslint-config-standard这个扩展,它也有自己的代码风格;如果通过 Prettier 格式化,standard 不干了;如果通过 standard 自动修复,那么 Prettier 又要报错了。

我们可以利用extends中最后一个覆盖前面扩展的特性,我们将eslint-config-prettier配置在 extends 最后,就能够关闭一些与Prettier的规则:

{
    extends: ["standard","plugin:prettier/recommended"]
}

之后需要在 setting.json 中配置

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
  "editor.codeActionsOnSave": {
        "source.fixAll": true
        ("source.fixAll.eslint": true)
    }
}