作为一个前端开发,要保证团队的代码质量和代码风格保持一致,就需要使用 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);
可以看到规则生效了。