成果守护者---ESLint

什么是eslint

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

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

ESLint 的初衷是为了让程序员可以创建自己的检测规则。ESLint 的所有规则都被设计成可插入的。ESLint 的默认规则与其他的插件并没有什么区别,规则本身和测试可以依赖于同样的模式。为了便于人们使用,ESLint 内置了一些规则,当然,你可以在使用过程中自定义规则。

ESLint 使用 Node.js 编写,这样既可以有一个快速的运行环境的同时也便于安装。

以上是来自官方的解释,说白了,就是一个静态代码检测工具,和Android开发中遇到的lint没啥区别,都是为了尽可能的将错误暴露在编码期,而不是运行期。

什么是eslint rule

eslint的rule就是代码的检测规则,每条rule对应一个检测规则,每条规则的启用与否在.eslintrc中进行配置,配置文件一般在eslint --init后自动生成,.eslintrc可以是json,js,yaml格式,规则的相关配置在这里进行

"rules": {
  "no-return-assign": 0, // 禁止在 return 语句中使用赋值语句
  "react/no-access-state-in-setstate": 0, // 在setState中访问this.state时上报
}
复制代码

可以看到在.eslintrc中配置了两条规则,一个是禁止在return语句中使用赋值语句,一个是提示在setState中访问this.state时上报,后面的0代表错误级别关闭规则,当然也可以使用“off"代替。eslint运行时会检测配置文件,会从当前目录逐层向外检测,并且不会停止,如果出现配置文件冲突,或者只希望使用内层的eslintrc配置文件,那么声明root:true,这样eslint就不会继续搜索外层的配置文件。

可以使下面的值之一:

  • "off" or 0 - 关闭规则
  • "warn" or 1 - 将规则视为一个警告(不会影响退出码)
  • "error" or 2 - 将规则视为一个错误 (退出码为1)

如何自定义rule

这里我们以在RN开发中提示FlatList增加initalNumberToRender为例,FlatList增加initalNumberToRender可以在一定程度上减少渲染,提高秒开率。

定义目录

ESLint 中的每个规则都有三个文件,以它的 ID 命名(例如,no-extra-semi)。

  • lib/rules 目录:源码文件 (例如,no-extra-semi.js)
  • tests/lib/rules 目录:测试文件 (例如,no-extra-semi.js)

如图:

截屏2022-01-15 下午7.12.42.png

代码实现

看一下flatlist-miss-initalnubertorender.js文件内容

/**
 * @fileoverview FlatList缺少initalNumberToRender属性
 */
"use strict";
​
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
​
/**
 * @type {import('eslint').Rule.RuleModule}
 */
const checkFlatListMissingProps = require('../checkFlatListMissingProps');
module.exports = {
  meta: {
    type: `suggestion`, // `problem`, `suggestion`, or `layout`
    docs: {
      description: "FlatList缺少initalNumberToRender属性",
      category: "Fill me in",
      recommended: false,
      url: null, // URL to the documentation page for this rule
    },
    fixable: null, // Or `code` or `whitespace`
    schema: [], // Add a schema if the rule has options
  },
​
  create(context) {
    // variables should be defined here
​
    //----------------------------------------------------------------------
    // Helpers
    //----------------------------------------------------------------------
​
    // any helper functions should go here or else delete this section
​
    //----------------------------------------------------------------------
    // Public
    //----------------------------------------------------------------------
​
    return {
      JSXOpeningElement(node) {
        checkFlatListMissingProps(context,node,'initialNumToRender')
      },
  };
  },
};
​
复制代码

可以看到前面的meta定义了规则的一些信息,包括类型,信息描述以及类别等等,注意doc里的东西一般会在ide的检测标识中展示出来。整个规则最关键的其实就是这个create函数了,eslint的原理也是很简单,遍历程序源代码,解析语法树中的节点,生成抽象语法树,构建访问者,遍历节点,根据节点中的信息来判断是否符合自己定义的规则,这里我们需要解析FlatList,并在它缺少initnalNumberToRender属性时报错,在vscode中效果如下

截屏2022-01-15 下午7.24.36.png

create函数返回一个对象,其中包含了 ESLint 在遍历 JavaScript 代码的抽象语法树 时,用来访问节点的方法。那么如何查看代码的抽象语法树以及相应的节点类型呢?这里使用一个工具网站 astexplorer.net/

截屏2022-01-15 下午7.33.09.png

如果所示,一个对应了一个JSXOpeningElement节点,所以我们就声明一个JSXOpeningElement用来处理该节点

JSXOpeningElement(node) {
        checkFlatListMissingProps(context,node,'initialNumToRender')
      }
复制代码

看一下checkFlatListMissingProps方法

module.exports =function checkFlatListMissingProps(context, node, propName) {
    if (node?.name?.name === 'FlatList') {
        let hasDataAttribute = false;
        const attributes = node.attributes;
        for (let i = 0; i < attributes.length; i++) {
            if (propName === attributes[i]?.name?.name) {
                hasDataAttribute = true;
                return;
            }
        }
        if (!hasDataAttribute) {
            context.report({
                node,
                message: `FlatList请确认添加${propName}属性`,
            });
        }
    }
}
​
复制代码

原理很简单,判断当前JSXOpeningElement节点下的所有JSXAttribute节点,如果不存在initalNumberToRender节点,那么就调用context在相应节点上给出提示信息。context 对象包含额外的功能,有利于规则完成他们的工作。顾名思义,context对象包含与规则上下文相关的信息。具体内容可以参考文档 eslint.bootcss.com/docs/develo…

什么是eslint plugin

每个插件是一个命名格式为 eslint-plugin-<plugin-name> 的 npm 模块,比如 eslint-plugin-jquery。插件中可以包含多个rules,一般插件的创建推荐使用 Yeoman generator工具进行创建,你也可是使用这个工具进行rule目录的创建。定义好的插件可以通过yarn或者npm发布到远端仓库。

如何自定义插件

通过Yeoman generator创建的插件模板,会有一个index.js文件

module.exports = {
    rules: requireIndex(__dirname + "/rules")
}
复制代码

这里会暴露所有插件对外暴露的规则,只有暴露的规则才能被引入的项目引用,但是这种写法有个弊端,就是你需要在项目的eslint配置文件中声明所有插件中的规则,并定义相应的错误级别,否则默认都是不起作用的,为了可以使用插件的默认配置,我们可以定义一个插件的配置属性。

// import all rules in lib/rules
module.exports = {
    rules: requireIndex(__dirname + "/rules"),
    configs: {
        recommand: {
            rules: {
                'plugin-name/rulename1': 2,
                'plugin-name/rulename2': 2
            }
        }
    }
}
​
复制代码

这样当你在eslint的配置文件中就不用逐个声明规则了,可以直接使用插件配置。

"extends": [
        "plugin:plugin-name/recommand"
    ]
复制代码

如何使用插件

插件的使用和普通npm包的引入没有什么区别,yarn add --dev eslint-plugin-,之后在eslint配置文件.eslintrc中注明使用的插件名称

"plugins": [
        "plugin-name"
    ]
复制代码

使用插件中的规则格式为"plugin-name/rule-name"

"rules": {
        "plugin-name/rule-name": "error"
    }
复制代码

如果插件存在相关配置,可以使用

"extends": [
        "plugin:plugin-name/recommand"
    ]
复制代码

最后

通过eslint,我们可以规范团队成员的代码,通过在编码期给出提示,保证团队成员写出规范和高效的代码,同时结合pipleline,可以做出进一步的强约束,提高犯错成本,保证代码质量

关注我的公众号:’滑板上的老砒霜‘

Supongo que te gusta

Origin juejin.im/post/7053935429183078414
Recomendado
Clasificación