资讯专栏INFORMATION COLUMN

十分钟了解eslint配置 && 编写自定义eslint规则

zqhxuyuan / 1745人阅读

摘要:的初衷是为了让程序员可以创建自己的检测规则。为了便于人们使用,内置了一些规则,当然,你可以在使用过程中自定义规则。所有的规则默认都是禁用的。在文件里的字段进行配置。如何编写一个知道了的原理,接下来可以自定义一个。

eslint介绍

ESLint 是一个开源的 JavaScript 代码检查工具,由 Nicholas C. Zakas 于2013年6月创建。代码检查是一种静态的分析,常用于寻找有问题的模式或者代码,并且不依赖于具体的编码风格。对大多数编程语言来说都会有代码检查,一般来说编译程序会内置检查工具。

JavaScript 是一个动态的弱类型语言,在开发中比较容易出错。因为没有编译程序,为了寻找 JavaScript 代码错误通常需要在执行过程中不断调试。像 ESLint 这样的可以让程序员在编码的过程中发现问题而不是在执行的过程中。

ESLint 的初衷是为了让程序员可以创建自己的检测规则。ESLint 的所有规则都被设计成可插拔的。为了便于人们使用,ESLint 内置了一些规则,当然,你可以在使用过程中自定义规则。所有的规则默认都是禁用的。

ESLint 使用 Node.js 编写。

eslint配置
配置方式

一般都采用.eslintrc.* 的配置文件进行配置, 如果放在项目的根目录中,则会作用于整个项目。如果在项目的子目录中也包含着.eslintrc文件,则对于子目录中文件的检查会忽略掉根目录中的配置,而直接采用子目录中的配置,这就能够在不同的目录范围内应用不同的检查规则,显得比较灵活。ESLint采用逐级向上查找的方式查找.eslintrc.*文件,当找到带有 "root": true 配置项的.eslintrc.* 文件时,将会停止向上查找。

在 package.json文件里的 eslintConfig 字段进行配置。

具体配置规则

以使用项目为例,简单介绍一下eslint的具体配置及作用:

module.exports = {
    parser: "babel-eslint", // parser指定解析器,默认的为espree。babel-eslint是一个Babel parser的包装器,这个包装器使得 Babel parser 可以和 ESLint 协调工作
    parserOptions: {
        sourceType: "module", // 设置为 "script" (默认) 或 "module"(ES6)。
        ecmaFeatures: { // 这是个对象,表示你想使用的额外的语言特性:
            jsx: true // 启用 JSX
        }
    },
    extends: ["eslint:recommended"], // 使用eslint推荐的规则作为基础配置,可以在rules中覆盖
    plugins: ["html", "vue", "prettier", "import"], // vue是eslint-plugin-vue的简写,此插件的作用是可以让eslint识别.vue中的script代码
    rules: { // 0或者off表示规则关闭,出错也被忽略;1或者warn表示如果出错会给出警告(不会导致程序退出);2或者error表示如果出错会报出错误(会导致程序退出,退出码是1)
        "no-console": "off",
        "prefer-const": "error",
        "prettier/prettier": "warn",
        "prefer-arrow-callback": "warn",
        "no-debugger": process.env.NODE_ENV === "production" ? 2 : 0
    },
    globals: { // 允许在代码中使用全局变量
        location: true,
        setTimeout: true
    }
};

具体的配置文档:http://eslint.cn/docs/user-guide/configuring
具体的eslint:recommended支持的规则:https://cn.eslint.org/docs/rules/

“extends”除了可以引入推荐规则,还可以以文件形式引入其它的自定义规则,然后在这些自定义规则的基础上用rules去定义个别规则,从而覆盖掉”extends”中引入的规则。

{
    "extends": [
        "./node_modules/coding-standard/eslintDefaults.js",
        // Override eslintDefaults.js
        "./node_modules/coding-standard/.eslintrc-es6",
        // Override .eslintrc-es6
        "./node_modules/coding-standard/.eslintrc-jsx",
    ],
    "rules": {
        // Override any settings from the "parent" configuration
        "eqeqeq": "warn"
    }
}

除了在配置文件中指定规则外,还可以在代码中指定规则,代码文件内以注释配置的规则会覆盖配置文件里的规则,即优先级要更高。平时我们常用的就是 `eslint-disable-next-line
`

忽略检查

可以通过在项目目录下建立.eslintignore文件,并在其中配置忽略掉对哪些文件的检查。需要注意的是,不管你有没有在.eslintignore中进行配置,eslint都会默认忽略掉对/node_modules/** 的检查。也可以在package.json文件的 eslintIgnore 字段进行配置。

eslint检查原理

要实现静态分析则需要自建一个预编译阶段对代码进行解析。

首先我们看看大部分编译器工作时的三个阶段:

解析:将未经处理的代码解析成更为抽象的表达式,通常为抽象语法树,即 AST。
转换:通过修改解析后的代码表达式,将其转换为符合预期的新格式。
代码生成:将转换后的表达式生成为新的目标代码。

对于eslint来说,规则校验发生在将JavaScript 代码解析为 AST 之后,遍历 AST 的过程中。eslint采用 Espree 来生成AST。具体的生成方法在这里。
我们可以使用AST explorer来查看代码被解析后生成的AST。

rules工作原理

首先来看看eslint源码中关于rules的编写。eslint中的rules源码存在于lib/rules下。每一个rules都是一个node模块,用module.exports导出一个meta对象及一个create函数。

module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "disallow unnecessary semicolons",
            category: "Possible Errors",
            recommended: true,
            url: "https://eslint.org/docs/rules/no-extra-semi"
        },
        fixable: "code",
        schema: [] // no options
    },
    create: function(context) {
        return {
            // callback functions
        };
    }
};

meta 代表了这条规则的元数据,如这条规则的类别,文档,可接收的参数 schema 等等。

create 返回一个对象,其中定义了一些在 AST 遍历访问到对应节点需要执行的方法等等。函数接受一个context对象作为参数,里面包含了例如可以报告错误或者警告的context.report()、可以获取源代码的context.getSourceCode()等方法,可以简化规则的编写。

function checkLastSegment (node) {
    // report problem for function if last code path segment is reachable
}

module.exports = {
    meta: { ... },
    create: function(context) {
        // declare the state of the rule
        return {
            ReturnStatement: function(node) {
                // 在AST从上向下遍历到ReturnStatement node 时执行
            },
            // 在AST 从下向上遍历到 function expression node 时执行:
            "FunctionExpression:exit": checkLastSegment,
            "ArrowFunctionExpression:exit": checkLastSegment,
            onCodePathStart: function (codePath, node) {
                // 在分析代码路径开始时执行
            },
            onCodePathEnd: function(codePath, node) {
                // 在分析代码路径结束时执行
            }
        };
    }
};

遍历 AST 的过程中会以“从上至下”再“从下至上”的顺序经过节点两次,selector 默认会在下行的过程中执行对应的访问函数,如果需要再上行的过程中执行,则需要添加:exit。

详细的原理在官方文档中有说明,点这里。
详细的代码路径分析在这里。

如何编写一个rules

知道了rules的原理,接下来可以自定义一个rules。每一个rules需要有三个以该规则名命名的文件,分别是:

在 lib/rules 目录下: 一个源文件(例如,no-extra-semi.js)

在 tests/lib/rules 目录下: 一个测试文件 (例如, no-extra-semi.js)

在 docs/rules 目录: 一个 markdown 文档文件 (例如, no-extra-semi)

接下来我们来编写一个简单的rules,例如禁止块级注释,当代码中使用了块级注释,eslint将报错。

rules文件:

// lib/rules/no-block-comments.js
module.exports = {
  meta: {
    docs: {
      description: "禁止块级注释",
      category: "Stylistic Issues",
      recommended: true
    }
  },

  create (context) {
    // 获取源代码
    const sourceCode = context.getSourceCode()

    return {
      Program () {
        // 获取源代码中所有的注释
        const comments = sourceCode.getAllComments()

        const blockComments = comments.filter(({ type }) => type === "Block")

        blockComments.length && context.report({
          node: node,
          message: "No block comments"
        })
      }
    }
  }
}

rules的测试文件:

// tests/lib/rules/no-block-comments.js
const RuleTester = require("eslint").RuleTester;
const rule = require("../../../lib/rules/no-block-comments");

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } }); // You do have to tell eslint what js you"re using

ruleTester.run("no-block-comments", rule, {
    valid: ["var a = 1; console.log(a)"],
    invalid: [
        {
            code: "var a = 1; /* block comments */ console.log(a)",
            errors: [
                {
                    messageId: "blockComments",
                    line: 1,
                    nodeType: "Block"
                }
            ]
        }
    ]
});

官网的working with rules文档中有关于如何编写一个rules的详细介绍。

如何使用自定义的rules

编写好的rules需要发布到npm上,作为一个eslint-plugin,在项目中下载下来才能够使用。例子中代码的npm在这里。

在项目中的配置:

// .eslintrc.js
module.exports = {
    ...
    "plugins": [
        "eslint-plugin-no-block-comments"
        // 你 publish 的 npm 包名称,可以省略 eslint-plugin
      ],
    "rules": { // 启用的规则及其各自的错误级别
        "no-console": "off",
        "no-block-comments/no-block-comments": 2 // 引用no-block-comments插件中的no-block-comments规则
    }
};

之后就可以对代码进行检查了。比如我要检查的代码如下:

// src/index.js
const a = 1;
/*
    这里是块级注释
*/
console.log(a);

在命令行中执行eslint src,就可以看到报错结果。

参考文章:

ESlint官网

ESLint 工作原理探讨

开发 eslint 规则

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106449.html

相关文章

  • 项目代码的格式化统一配置 Prettier & ESLint

    摘要:以前没时间过,每次项目编辑器的插件就关掉,老项目都没注意过相关的代码规范,这次新项目加入进去实践下三个插件功自动有些规则是冲突的,需要确定优先顺序,其他插件进行自定义化的配置都可以自动保存格式化的功能用和写出高质量代码在中对两者进行配置使用 以前没时间过eslint,每次项目vscode 编辑器的eslint插件就关掉eslint,老项目都没注意过相关的代码规范,这次新项目加入进去实践...

    Yu_Huang 评论0 收藏0
  • 代码风格统一:commitlint & eslint & standard-vers

    摘要:配置添加包配置此处如果不使用需要将替换为效果代码提交的格式不符合标准就会直接被拒绝。 Commitlint 配置 添加包 yarn add @commitlint/cli @commitlint/config-conventional husky -D 配置package.json husky: { hooks: { // 此处如果不使用husky 需要将H...

    lieeps 评论0 收藏0
  • 前端代码质量进阶:定义 eslint 规则校验业务逻辑

    摘要:自定义规则校验代码业务逻辑是社区中主流的工具,提供的大量规则有效的保障了许多项目的代码质量。本文将介绍如何通过自定义检查规则,校验项目中特有的一些业务逻辑,如特殊作用域特殊使用规范性等。 自定义 eslint 规则校验代码业务逻辑 eslint 是 JavaScript 社区中主流的 lint 工具,提供的大量规则有效的保障了许多项目的代码质量。本文将介绍如何通过自定义 eslint ...

    Coly 评论0 收藏0
  • 如何使用vite搭建vue3项目详解

      须知:使用vite需要node版本在12以上  一:npm构建  1、npm init vite@latest  2、Project name:(项目名称)  3、Select a framework:(选择要用什么构建自己的项目,这边选vue)然后会有两个选项一个是vue(vue+js) ,一个是vue+ts,要依照自己需求做选择  4、cd到项目下npm install 安装一下依赖  注...

    3403771864 评论0 收藏0
  • [译]JavaScript lint工具的比较

    摘要:工具帮助避免在编写时出现愚蠢的错误。并不检测潜在的,比如,未使用的变量或意外的全局变量等。在提到的所有工具中,它具有最广泛的功能支持。使用工具是捕获问题的良好步骤,但只能看到规则允许的错误。也可用于此目的。 Lint工具帮助避免在编写JavaScript时出现愚蠢的错误。尽管有多年的经验,我仍然键入不正确的变量名称,出现语法错误,以及忘记正确地处理error。在浪费自己时间,或更糟糕地...

    luck 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<