Skip to content

代码校验规则

Eslint

eslint是针对javascript/typescript的一种代码校验工具并报告或修改校验发现的问题,如语法或风格相关问题,使代码风格统一,并且避免一些语法或低级错误。

初始化

在已有package.json文件的基础上,运行eslint的初始化配置。

shell
npm init @eslint/config

$ npm init @eslint/config
 How would you like to use ESLint? · problems
 What type of modules does your project use? · esm

选择想要的校验配置,最后会生成一个eslint的配置文件。

js
module.exports = {
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:vue/vue3-essential"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "parser": "@typescript-eslint/parser",
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint",
        "vue"
    ],
    "rules": {
        "semi": ["error", "always"],
        "quotes": ["error", "double"]
    }
}

配置文件格式

eslint的配置文件执行环境是node,package.json的type字段没有时,是commonjs格式,.eslintrc.js文件名可以正常运行。如果指定type: module,这时是esm格式,配置文件的名称要写成.eslintrc.cjs,扩展名必须是.cjs,这是因为当前eslint不支持esm格式。如果项目根目录存在多个目录时,按以下顺序的优先先匹配的先执行:

  1. .eslintrc.js
  2. .eslintrc.cjs
  3. .eslintrc.yaml
  4. .eslintrc.yml
  5. .eslintrc.json
  6. package.json

使用配置文件

如果同级目录有.eslintrc.js,会忽略package.json中的eslintConfig字段,优先使用配置文件的规则。 如果项目多个层级目录里都有.eslintrc.js配置,最底文件会往上层目录寻找其他的.eslintrc.js配置合并,直到某个配置文件里有root属性为true时则停止往上寻找,如果都没有root为true,则一直找到根目录。也就是说外层目录如果有.eslintrc.js配置文件,会影响到内层目录。 当然如果最内层目录的配置文件有root为true的属性,也不会往上合并。

扩展配置文件

扩展配置是在配置文件里添加extends属性,extends字段可以是字符串,也可以是字符串数组。字符串的值可以是当前项目其他eslint配置文件的路径,也可以是共享配置的名称,也可以是eslint:recommended或是eslint:all

扩展定义

配置文件使用扩展后,可以继承另一个配置文件的所有特征,包括规则、插件、和语言选项并修改所有选项。 它有三种配置,定义下: 基本配置:被扩展的配置Config 派生配置:扩展基础配置的配置SuperConfig 结果的实际配置:将派生配置合并到基础配置的结果merge(Config, SuperConfig)

共享配置包

就是一个npm包,里面包含eslint常用的公共配置用于其他项目扩展 默认都是带有eslint-config-前缀的,在写配置时可以省略前缀,解析后会默认带上:如 extends: standart, => 实际是解析 eslint-config-standard。

使用插件配置

插件不仅可以添加新规则,也可以导出可共享配置。在使用插件时可以省略eslint-plugin-前缀,如使用typescript和vue插件里的配置时:

  1. 先安装
shell
pnpm add -D @typescript-eslint/eslint-plugin eslint-plugin-vue
  1. 配置extends
js
extends: [
    'eslint:recommended',
    // 下面的都省略了eslint-plugin,如vue/vue3-recommended实际是eslint-plugin-vue/vue3-recommended
    
    // 使用插件@typescript-eslint/eslint-plugin里的配置@typescript-eslint
    'plugin:@typescript-eslint',
   
    // 使用eslint-plugin-vue里的配置vue/vue3-recommended
    'plugin:vue/vue3-recommended',
]

eslint:recommended配置是常见问题的核心规则子集,这是eslint内置的

基于glob模式配置

某些代码需要更精细化的配置时可以使用overrides配置覆盖其他配置,overrides里可以使用glob匹配模式。 overrides的glob模式使用的是minimatch语法。

js
{
  "rules": {
    "quotes": ["error", "double"]
  },

  "overrides": [
    {
      "files": ["bin/*.js", "lib/*.js"],
      "excludedFiles": "*.test.js",
      "rules": {
        "quotes": ["error", "single"]
      }
    }
  ]
}

语言配置项

环境变量

不同环境有不同的全局变量,可以通过配置文件的env字段配置环境,可以提供相应的预设变量。 可选的环境有:

js
{
    "env": {
        "node": true, // Node.js 的全局变量和 Node.js 的范围。
        "browser": true, // 浏览器全局变量。
         // CommonJS 全局变量和 CommonJS 范围(用于使用 Browserify/WebPack 的纯浏览器代码)。
        "commonjs": true,
        // 启用除模块之外的所有 ECMAScript 6 功能(这会自动将解析器设置为 6)。
        "es6": true,
        // 添加所有 ECMAScript 2016 的全局变量,并自动将解析器选项 ecmaVersion 设置为 7。
        "es2016|7|8...": true
    }
}

这里的环境变量可以同时使用多个不是互斥的。 除了了使用配置文件配置env字段,也可以在js文件中使用注释的形式使用

js
/* eslint-env node, browser */

全局变量

代码中有些变量在上下文是没有定义也没有引入的,这些属于全局变量。如果不告诉eslint规则,会当成使用未定义变量。这时可以在配置文件添加全局属性或当前文件里使用注释的形式标注成全局属性

注释形式如下

js
/* globals var1, var2 */
/* global var1:writable, var2:writable */

配置文件如下

js
{
    "globals": {
        "var1": true, // 和"writable"值一样,当前全局变量可配置
        "var2": "off",// 关闭,当前变量不是全局变量,不能使用
        "var3": false,// 和 "readable"  "readonly"值一样,可读,不能修改
    }
}

规则配置rules

属性名对应规则名称,属性值是一个数组。 数组第一个元素的值规则的错误级别 "off" 或 0,关闭规则 "warn" 或 1,启用并告警(不影响退出) "error" 或 2,启用并报错(错误时退出代码为1) 数组第二个元素的值是规则值配置,不值在同一规则有不同表现。

在注释是使用

js
/* eslint semi: off, quotes: warn */

// 禁用两个规则
/* eslint-disable semi, quotes */

// 当前文件禁用
/* eslint-disable */

// 当前文件启用
/* eslint-enable */

配置文件中使用

js
"rules": {
    "semi": ["error", "always"],
    "quotes": ["error", "double"]
}

settings.json配置保存进自动格式化

js
"editor.codeActionsOnSave": {
    // 使用eslint来fix,包括格式化会自动fix和代码质量检查会给出错误提示
    "source.fixAll.eslint": true
 }

插件和解析器

插件

插件主要是扩展eslint,可以包括:

  • 自定义规则。
  • 自定义配置。
  • 自定义环境。
  • 自定义处理器,从其他类型文件提取js代码,或以提示前进行预处理。

配置插件,默认是有eslint-plugin-前缀的,可以写完整,也可以只写名称

js
{
    "plugins": [
        "plugin1", // eslint-plugin-plugin1
        "eslint-plugin-plugin2",
        
        "@jquery/jquery", // @jquery/eslint-plugin-query
        "@foobar", // @foobar/eslint-plugin
    ]
}

指定处理器

处理器使用从其他类型文件提取js,以供eslint处理。插件可以提供处理器 配置处理器

js
{
    plugins: ["vue"]
    processor: "vue/sfp-processor" // 插件名称使用"/"连接处理器名称
}

如果要为特定类型文件提供处理器,可以让overrides和processor一起配合使用

js
{
  "plugins": ["vue"],
  "overrides": [
      {
          "files": ["*.vue"],
          "processor": "vue/sfp-processor"
      }
  ]
}

解析器

eslint默认使用的解析器是espree, 如果代码与eslint的解析器不兼容,可以自定义解析器,解决js代码解析成抽象语法树,供eslint评估。 自定义解析器满足:

  1. 是一个可以在使用解析器的配置文件中加载的node模块,也就是说,可以使用npm单独安装。
  2. 符合解析器接口。

注意:有些解析器和eslint兼容,但不保证eslint正确工作。

与eslint兼容的解析器:

  • Esprima
  • @babel/eslint-parser 使用babel解析器与eslint兼容的包装器
  • @typescript-eslint/parser, 一个将typescript转换为与estree兼容形式的解析器,可以正常在eslint中使用。

使用解析器时,仍然需要配置parserOptions 选项,解析需要parserOptions 开启某些特色功能。

js
{
    "parserOptions": {
        "ecmaVersion": "latest|6|2017" // 指定ECAMScripa的语法版本
        "sourceType": "script", // 默认是script,module如果js是EACMScript模块
        "ecmaFeatures": { // 配置你想使用的额外的语言特性 
          "globalReturn": false,  // 允许在全局作用域下使用 return 语句
          "jsx": true,            // 启用 jsx
          "impliedStrict": false, // 启用全局 strict mode (如果 ecmaVersion 是 5 或更高)
        }

    }
}

忽略文件

  1. 可以在配置文件中添加ignorePatterns字段配置,
  2. 也可以添加.eslintignore

在vscode中使用

安装eslint扩展 在vscode中使用eslint扩展,必须在安装或全局安装eslint库才能使用

Stylelint

stylelint在配置和使用上都和eslint差不多。

Prettier

参考:https://juejin.cn/post/7156893291726782500

作用

主是对代码风格规范的统一,如每行最大长度,单引号还是双引号,使用tab还是空格。不仅对JS/TS,对其他语言也可以格式化,如:vue/hmtl/scss/less等。不具备代码质量检查的能力

和eslint对比

eslint也有格式化功能,为什么还要使用prettier。

  • eslint安装配置比较麻烦,而且lint的速度也不快。
  • prettier不仅针对js,也可以格式各种流行语言。
  • prettier配置简单,安装插件,配置保存自动格式化即可。

在vscode中使用

安装插件即可使用,这个插件是默认开启的,不需要在项目中安装prettier。

在vscode启用默认格式化工具为prettier,可以手动配置: "editor.defaultFormatter": "esbenp.prettier-vscode"

json
// 默认格式化工具选择prettier
"editor.defaultFormatter": "esbenp.prettier-vscode",

配置为指定语言默认格式化器

json
"[javascript]": {
    // js默认格式化工具选择prettier
    "editor.defaultFormatter": "esbenp.prettier-vscode",
}

在vscode里保存文件时是否使用默认工具代码格式化配置:"editor.formatOnSave": true

json
// 保存的时候自动格式化
"editor.formatOnSave": true

prettier.requireConfig

默认值为false,没有配置文件可以使用插件内置的。

在vscode的配置文件里配置了 "prettier.requireConfig": true // 需要Prettier的配置文件,则项目里需要prettier的配置文件,否则保存也不会格式化,输出提示: Require config set to true and no config present. Skipping file.

配置文件

配置文件默认是.prettier,也可以使用.editorconfig。优先级是: .prettier > .editorconfig > vscode默认配置。 prettier配置,插件内置的、setting.json配置的,还有项目的配置文件.prettierrc.js,本地文件的优先,可以看vscode的输出工具里打印的配置。

js
module.exports = {
  // 常用配置相关解释
  printWidth: 100, // 超过最大值换行
  tabWidth: 4, // 缩进字节数
  useTabs: false, // 缩进不使用tab,使用空格
  semi: true, // 句尾添加分号
  singleQuote: true, // 使用单引号代替双引号
   // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
  proseWrap: 'preserve',
  arrowParens: 'avoid', //  (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
  bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
  disableLanguages: ['vue'], // 不格式化vue文件,vue文件的格式化单独设置
  endOfLine: 'auto', // 结尾是 \n \r \n\r auto
  eslintIntegration: false, //不让prettier使用eslint的代码格式进行校验
  htmlWhitespaceSensitivity: 'ignore',
  ignorePath: '.prettierignore', // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
  jsxBracketSameLine: false, // 在jsx中把'>' 是否单独放一行
  jsxSingleQuote: false, // 在jsx中使用单引号代替双引号
  parser: 'babylon', // 格式化的解析器,默认是babylon
  requireConfig: false, // Require a 'prettierconfig' to format prettier
  stylelintIntegration: false, //不让prettier使用stylelint的代码格式进行校验
  trailingComma: 'es5', // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
}

和eslint冲突

由于prettier和eslint都可以格式化代码,所以可能会冲突,出现冲突的原因:

  • 重叠的格式化规则不一致
  • vscode同时开启二者进行格式化
json
{
    "editor.formatOnSave": true, // 开启格式保存
    "editor.defaultFormatter": "esbenp.prettier-vscode", // 使用prettier格式化
    "eslint.enable": true, // eslint开启
    "editor.codeActionsOnSave": {
       "source.fixAll.eslint": true // 代码保存使用eslint格式化
     }
}

解决冲突

方案一

主要是解决冲突规则问题,根据社区常用的解决方案: 在使用eslint作为代码格式化工具时,关闭可能与prettier有冲突的格式化规则,把prettier当做一个linter规则。 主要是使用下面两个包:

eslint-config-prettier,会关闭eslint中有关代码格式化的配置。这个只是提供一份eslint的配置规则,而在eslint-plugin-prettier中会继承eslint-config-prettier配置。

eslint-plugin-prettier,把prettier配置成eslint的一个插件,让其当做一个linter规则来支行,查看官网 注意:eslint-plugin-prettier需要安装prettier依赖 在.eslintrc.js中配置eslint-plugin-prettier

json
{
    "extends": [
        "plugin:prettier/recommonded"
    ]
}

plugin:prettier/recommonded做的事是在.eslintrc中配置:

json
{
  "extends": ["prettier"], // 使用eslinst-config-prettier中的配置项
  "plugins": ["prettier"], // 注册该prettier插件
  "rules": {
    "prettier/prettier": "error", // 在eslint中运行prettier,并启用该插件提供的规则
    "arrow-body-style": "off", // 关闭规则
    "prefer-arrow-callback": "off" // 关闭规则
  }
}

这样配置后,eslint在格式后就不会和prettier冲突了。

方案二

方案一,把规则冲突屏避掉了,但保存时还是会有两次格式化的,只是最后格式化内容输出一致。 由于eslint只能javascript/typescript/javascriptreact,校验格式化,对其他无效,但是prettier可以。这样在配置文件时可以关掉prettier对javascript/typescript/javascriptreact的格式,由eslint格式化,其他语言则由prettier格式化。

json
{
    "editor.formatOnSave": true, 
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    //针对共用的语言如JS、TS和JSX关闭文件保存自动格式化功能,通过eslint来做这件事 
    "[javascript]": { 
        "editor.formatOnSave": false 
    }, 
    "[javascriptreact]": {
        "editor.formatOnSave": false
    },
    "[typescript]": {
        "editor.formatOnSave": false
    },
    "editor.codeActionsOnSave": { //告诉ESLint插件在保存时运行 
        "source.fixAll.eslint": true 
    }
}

CLI命令

CLI命令 prettier --write . 格式当前目录的文件及所有子目录对应的文件并重写,这是递归操作。

Vscode editor.formatOnSave vs editor.codeActionsOnSave

editor.formatOnSave 主要配置保存文件时使用的默认格式化器。 editor.codeActionsOnSave,主要是配置保存文件时需要执行的动作,可能是格式化器命令,也可以是其他命令。 这两个配置都有格式化功能,这也是冲突的原因。但是后者不仅可以配置格式化器,也可以执行其他更多的代码命令。