作为一个前端开发,要保证团队的代码质量和代码风格保持一致,就需要使用eslint来进行代码检查,一个好的eslint配置可以让团队提高开发的幸福感。市面上已经有很多大公司团队定制了自己的eslint规则,例如:国外有airbnb的eslint-config-airbnb
,谷歌的eslint-config-google
,国内的有阿里的eslint-config-ali
等等。
当然并非大厂的规则就一定适用于我们日常工作,所以有时候拿来即用也不是很方便,我们需要根据自己的项目需求来定制一套适合自己的eslint规则。
插件概念
要开发一个 eslint 插件,需要先了解以下几个概念:
AST
抽象语法树,一种用于表示代码结构的树形数据结构。eslint 默认使用 espree 作为其解析器,将源代码转换为AST(抽象语法树)。espree 适用于ES5、ES6和ES7的JavaScript解析器,当然我们也可以配置其他解析器,例如@babel/eslint-parser,@typescript-eslint/parser等等。
Context
eslint 执行过程的上下文环境变量,可以在当前执行检测的时候获取规则配置,访问源码,报告错误,修复语法等功能。
Rule
eslint 规则是一个函数,接受一个 context 对象,返回一个 visitor 对象,可以通过visitor获取解析的节点信息并进行相应的处理。
eslint插件脚手架
可以通过 yo 命令来安装脚手架,yo 是 yeoman 的命令行工具,yeoman 是一个脚手架工具,可以通过它来快速搭建项目的基础结构。如果没有安装 yo,可以通过npm install -g yo
来安装。
接下来安装 eslint 插件脚手架
npm install -g generator-eslint
安装完成后,我们创建一个文件夹,命名最好以eslint-plugin-xxx
开头,然后到文件夹下运行yo eslint:plugin
,会帮我们创建一个简单的eslint项目文件。
自定义规则实现
我们在刚创建的eslint-plugin-xxx
文件夹根目录下运行yo eslint:rule
,我们来简单实现一个功能,限制不在项目里面写console.log(xx)
等代码
我们在lib/rules/no-console-log.js
文件编写代码如下:
module.exports = {
meta: {
type: "problem", // `problem`, `suggestion`, or `layout`
messages: {
noConsoleLog: "no console log",
},
docs: {
description: "no console log",
recommended: false,
url: null,
},
fixable: null, // Or `code` or `whitespace`
schema: [], // Add a schema if the rule has options
},
create(context) {
// 返回访问者对象
return {
// 当访问到CallExpression节点时触发
CallExpression(node) {
// 如果调用表达式的callee是console.log
if (
node.callee.type === "MemberExpression" &&
node.callee.object.name === "console" &&
node.callee.property.name === "log"
) {
// 报告错误
context.report({
node,
messageId: "noConsoleLog",
});
}
},
};
},
};
在tests/lib/rules/no-console-log.js
文件的内容如下:
/**
* @fileoverview no console log
* @author kelen
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const rule = require("../../../lib/rules/no-console-log"),
RuleTester = require("eslint").RuleTester;
//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------
const ruleTester = new RuleTester();
ruleTester.run("no-console-log", rule, {
// 有效的测试用例
valid: [
// 不包含console.log的代码
"console.error('error');",
"console.warn('warn');",
"console.info('info');",
"console.debug('debug');",
"console.trace('trace');",
"console.dir('dir');",
"console.dirxml('dirxml');",
"console.table('table');",
"console.time('time');",
"console.timeLog('timeLog');",
"console.timeEnd('timeEnd');",
"console.group('group');",
"console.groupCollapsed('groupCollapsed');",
"console.groupEnd('groupEnd');",
"console.clear('clear');",
"console.count('count');",
"console.countReset('countReset');",
"console.assert('assert');",
],
// 无效的测试用例
invalid: [
// 包含console.log的代码,应该报告错误
{
code: "console.log('log');",
errors: [{ messageId: "noConsoleLog" }],
},
],
});
接下来,执行npm run test
,可以看到输出结果如下
最后我们可以把eslint发布到npm仓库里,然后就可以在其他项目里面使用了。
项目引入
在需要引入自定义插件的项目里安装该插件,npm i eslint-plugin-kelen -D
,然后在.eslintrc.js
文件配置如下。
module.exports = {
root: true,
plugins: ["kelen"],
rules: {
"kelen/no-console-log": "error",
},
};
在项目输入console.log(12313);
可以看到规则生效了。