ESLint 深度解析:原理、规则与插件开发实践

在前端开发的复杂生态中,保障代码质量与规范性是构建稳健、可维护项目的基石。ESLint 作为一款强大的代码检查工具,其默认规则与插件能满足多数常见需求,但面对特定团队规范或项目独特要求,自定义 ESLint 插件便成为有力的扩展手段。本文将深入探讨如何打造自定义 ESLint 插件,并结合实际案例,详细阐述从创建到应用的全过程。

一、ESLint 基础回顾

ESLint 通过静态分析代码,将其转换为抽象语法树(AST),进而依据规则对代码进行细致检查。这一过程始于对代码的解析,默认使用 Espree 解析器,它将代码转化为树形结构,每个节点代表一种语法结构。例如,对于简单代码let num = 10;,在 AST 中会呈现为VariableDeclaration节点。

  • VariableDeclaration节点 :用于表示变量声明。它包含以下重要属性:

    • declarations :是一个数组,存放变量声明符。在let num = 10;中,这个数组只有一个元素,即表示num变量的声明符。
    • kind :表示声明的类型,如let、const或var。在上述例子中,kind的值为let。

ESLint 利用这些 AST 信息,对照规则库,找出代码中的潜在问题,如未使用的变量、错误的语法等。

二、自定义插件的需求场景


在团队协作项目中,统一的代码风格和规范至关重要。除了常规的代码格式与最佳实践,还可能存在一些特殊要求。例如,为了维护代码的文明性与专业性,我们要求代码中不得出现诸如 “sb250”“fuck” 等不文明、不专业的词汇。这类需求无法通过 ESLint 的默认规则实现,因此需要开发自定义插件来满足。

三、自定义 ESLint 插件开发流程

(一)工程搭建

  • 初始化项目

    • 首先确保全局安装了yo和generator - eslint。若未安装,可通过以下命令进行安装:
npm i -g yo
npm i -g generator-eslint
  • 然后创建一个新目录用于插件项目,例如eslint - plugin - yinzhixiaxue,并进入该目录:
mkdir eslint-plugin-yinzhixiaxue
cd eslint-plugin-yinzhixiaxue
  • 执行yo eslint:plugin命令,这是一个交互式命令,需要填写相关信息:

    • 插件名称:例如eslint-plugin-yinzhixiaxue。
    • 插件描述:描述插件的功能,如 “用于检查代码中是否存在不文明词汇的 ESLint 插件”。
    • 是否包含自定义规则:选择Yes。
    • 是否需要处理器:根据实际需求选择,通常对于简单的规则检查选择No。
  • 安装依赖

    • 插件开发依赖eslint和eslint-utils库,通过以下命令安装:
npm install eslint eslint-utils --save - dev

(二)创建规则

  • 生成规则文件

    • 在项目目录下执行npx yo eslint:rule命令,同样是交互式操作:

      • 规则名称:例如no-offensive-words。
      • 规则描述:如 “禁止在代码中使用不文明词汇”。
      • 不通过的案例代码:可输入包含不文明词汇的代码示例,如let message = “fuck you”;。
    • 完成后,项目目录结构中会生成lib/rules/no-offensive-words.js文件,该文件用于编写具体的规则逻辑。

(三)规则配置与编写

  • 规则配置(meta对象)

在lib/rules/no-offensive-words.js文件中,首先定义meta对象,用于描述规则的元信息:\

module.exports = {meta: {type: 'problem', // 表示该规则识别的代码可能会导致问题,需要优先解决,取值还可以是'suggestion'(建议优化代码)或'layout'(关注代码布局,如空格、分号等)docs: {description: '禁止在代码中使用不文明词汇', // 规则的详细描述category: 'Custom Rules', // 规则的分类,便于在规则列表中进行归类展示recommended: true, // 表示该规则是否推荐使用,若为true,在继承相关配置时可能会默认启用该规则url: null // 规则文档的链接,可指向详细介绍该规则的页面,这里暂设为null},messages: {noOffensiveWords: '代码中不允许使用不文明词汇' // 定义规则触发时的错误提示信息,这里的'noOffensiveWords'是一个自定义的标识符,可在后续代码中引用},fixable: null, // 表示该规则是否支持自动修复,null表示不支持,'code'表示可修复代码问题,'whitespace'表示可修复空格相关问题schema: [] // 用于定义规则的配置选项,这里为空表示该规则没有额外的配置参数},// 规则具体实现将在create函数中编写
};
  • AST结构分析与规则编写(create函数)

ESLint 通过遍历 AST 来应用规则,因此需要了解代码对应的 AST 结构。对于代码let message = “fuck you”;,在 AST Explorer(https://astexplorer.net/)中解析后,VariableDeclaration节点包含message变量的声明信息,而变量的初始值"fuck you"则存储在init属性指向的Literal节点中。

我们使用Literal节点是因为在这个规则中,我们关注的是字符串字面量中是否包含不文明词汇。Literal节点专门用于表示各种字面量,如字符串、数字、布尔值等。在检查不文明词汇时,我们只需要关心字符串类型的字面量,所以使用Literal节点来获取并检查变量值。

基于此,编写create函数来实现规则:\

module.exports = {meta: {// 省略meta部分已有的内容},create: function (context) {const offensiveWords = ['sb250', 'fuck'];return {Literal(node) {if (typeof node.value ==='string') {offensiveWords.forEach((word) => {if (node.value.includes(word)) {context.report({node,messageId: 'noOffensiveWords'});}});}}};}
};


在上述代码中:

  • 定义了一个包含不文明词汇的数组offensiveWords。
  • 在create函数返回的对象中,使用Literal节点访问方法。当 ESLint 遍历 AST 遇到Literal节点(通常用于表示字符串、数字等字面量)时,若其值为字符串类型,则检查该字符串是否包含offensiveWords中的词汇。若包含,则使用context.report方法报告错误,错误信息使用meta.messages中定义的noOffensiveWords。

(四)配置规则组

在lib/rules/index.js文件中,将新创建的规则集成到插件中:

const requireIndex = require('requireindex');
const rules = requireIndex(__dirname + '/rules');
module.exports = {rules,configs: {recommended: {plugins: ['yinzhixiaxue'],rules: {'yinzhixiaxue/no-offensive-words': 'error'}}}
};


这里通过requireIndex引入自定义规则,在configs中定义了recommended配置组,将no-offensive-words规则设置为error级别,即一旦违反该规则,ESLint 将抛出错误。

(五)补充测试用例

在tests/lib/rules/no-offensive-words.js文件中编写测试用例,以验证规则的正确性:

const rule = require('../../../lib/rules/no-offensive-words');
const RuleTester = require('eslint').RuleTester;const ruleTester = new RuleTester();
ruleTester.run('no-offensive-words', rule, {valid: ['let message = "Hello world";','const num = 10;'],invalid: [{code: 'let message = "sb250 is not allowed";',errors: [{ messageId: 'noOffensiveWords' }]},{code: 'const greeting = "fuck this";',errors: [{ messageId: 'noOffensiveWords' }]}]
});


测试用例分为valid和invalid两组:

  • valid组包含符合规则的代码示例,这些代码应通过规则检查。
  • invalid组包含违反规则的代码示例,每个示例都指定了预期的错误信息messageId,用于验证规则是否按预期触发错误。

四、自定义插件的使用

(一)插件安装

  • 本地调试

在插件项目目录下执行npm link,然后在需要使用该插件的项目目录下执行npm link eslint-plugin-yinzhixiaxue。

  • 发布安装

将插件发布到 npm 仓库后,在项目中通过npm install eslint-plugin-yinzhixiaxue --save - dev进行安装。

(二)项目配置

在项目的.eslintrc文件中,添加插件配置:

{"extends": ["plugin:yinzhixiaxue/recommended"],"parserOptions": {"ecmaVersion": 6,"sourceType": "module"}
}


这里通过extends继承了eslint-plugin-yinzhixiaxue插件的recommended配置组,同时根据项目需求配置了parserOptions,例如支持 ES6 语法和模块语法。

(三)关于 extends 和 plugins 的深入理解

在 ESLint 的配置体系中,extends和plugins扮演着不同但又紧密关联的角色。

extends主要用于继承已有的配置集合 ,它可以是一个配置文件的路径、可共享配置的名称,或是plugin:插件名/配置组名的形式。以"extends": [“plugin:react/recommended”]为例,它会一次性启用react插件中recommended配置组里预先定义好的多个规则 ,这些规则涵盖了插件作者认为在大多数情况下适合项目使用的代码检查规范,比如react/jsx-uses-react、react/jsx-uses-vars等规则会同时生效,无需开发者逐个配置。这大大简化了配置流程,确保项目遵循特定插件推荐的整体规则集。

plugins则是用于引入第三方插件 ,扩展 ESLint 的功能边界。在使用插件前,需要先通过npm安装插件,然后在.eslintrc文件的plugins数组中添加插件名,如"plugins": [“eslint-plugin-demo”] 。引入插件后,若想启用插件中的规则,有两种常见方式。一是在rules中单独配置,例如想启用eslint-plugin-demo插件中的rule1规则,可以设置"eslint-plugin-demo/rule1": “error” ,这种方式适用于对插件规则有精细化控制,只启用部分规则的场景;二是结合extends,通过继承插件提供的配置组来批量启用规则,就像前面提到的"extends": [“plugin:react/recommended”] 。

extends会默认开启当前的所有,plugin需要自己手动开启

extends侧重于对已有配置的复用,让开发者能够快速应用一套成熟的规则体系;而plugins更专注于引入新的功能,无论是自定义规则还是特殊文件处理器。在实际项目中,二者通常相互配合,开发者可以根据项目的具体需求,先用plugins引入插件,再巧妙运用extends来启用插件中合适的配置组,从而精准定制出符合项目特点的代码检查方案。

通过以上步骤,我们成功创建并应用了一个自定义 ESLint 插件,能够有效检查代码中是否存在不文明词汇,进一步提升了代码的规范性与专业性,为团队协作和项目维护提供了有力保障。在实际开发中,可根据更多具体需求,灵活扩展和调整自定义插件的规则,以满足不断变化的项目要求。

技术交流沟通➕V:yinzhixiaxue

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/28713.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rust编程实战:实现3d粒子渲染wasm

源码 纯js实现 fps: wasm实现 通过对比可以看出来 wasm 实现的计算比纯js刷新相对稳定。

开放鸿蒙OpenHarmony 5.0.0 Release 兼容性测试实战经验分享

OpenHarmony 5.0版本的发布时间是2024年12月20日至21日。这个版本带来了许多新特性和改进。现在5.0出了两个release 版本,分别是5.0.0和5.0.1。 就在5.0版本发布不到2周的时间内,2025年01月01日起,不支持新产品基于老分支(OpenHar…

deepseek在pycharm 中的配置和简单应用

对于最常用的调试python脚本开发环境pycharm,如何接入deepseek是我们窥探ai代码编写的第一步,熟悉起来总没坏处。 1、官网安装pycharm社区版(免费),如果需要安装专业版,需要另外找破解码。 2、安装Ollama…

23种设计模式一览【设计模式】

文章目录 前言一、创建型模式(Creational Patterns)二、结构型模式(Structural Patterns)三、行为型模式(Behavioral Patterns) 前言 设计模式是软件工程中用来解决特定问题的一组解决方案。它们是经过验证…

spring boot整合flyway实现数据的动态维护

1、简单介绍一下flyway Flyway 是一款开源的数据库版本控制工具,主要用于管理数据库结构的变更(如创建表、修改字段、插入数据等)。它通过跟踪和执行版本化的迁移脚本,帮助团队实现数据库变更的自动化。接下来简单介绍一下flyway…

致远电子三合一8路串口服务器

ZLG致远电子全新推出国产化透传型三合一8路串口服务器,让用户轻松实现串口信号与以太网的无缝数据交互。性能强悍,等你来评,还有机会获得新年第一份心意! GCOM88-2NET-P硬件速览 国产高性能816MHz处理器; 2路10/100M自…

20250304解决在飞凌的OK3588-C的Linux R4下解决使用gstreamer保存的mp4打不开

sync poweroff rootok3588:/# sync rootok3588:/# sync rootok3588:/# cd 107 rootok3588:/107# ls -l total 0 rootok3588:/107# sync rootok3588:/107# poweroff 20250304解决在飞凌的OK3588-C的Linux R4下解决使用gstreamer保存的mp4打不开 2025/3/4 10:58 缘起&#xff1a…

安路FPGA移植Cortex-M0内核

本文是关于基于安路FPGA EG4S20BG256移植Cortex M0内核的笔记。硬件平台使用硬木课堂的安路核心板,软件使用安路的TD5.6.2和keil5。(博主刚学FPGA不久,文中有不足之处请帮忙指出) 在移植之前,博主看了网上很多的文章、…

STM32——串口通信 UART

一、基础配置 Universal Asynchronous Receiver Transmitter 异步,串行,全双工 TTL电平 :高电平1 低电平0 帧格式: 起始位1bit 数据位8bit 校验位1bit 终止位1bit NVIC Settings一栏使能接受中断。 之前有设置LCD,…

flink集成tidb cdc

Flink TiDB CDC 详解 1. TiDB CDC 简介 1.1 TiDB CDC 的核心概念 TiDB CDC 是 TiDB 提供的变更数据捕获工具,能够实时捕获 TiDB 集群中的数据变更(如 INSERT、UPDATE、DELETE 操作),并将这些变更以事件流的形式输出。TiDB CDC 的…

DeepSeek×博云AIOS:突破算力桎梏,开启AI普惠新纪元

背景 在全球人工智能技术高速迭代的背景下,算力成本高企、异构资源适配复杂、模型部署效率低下等问题,始终是制约企业AI规模化应用的关键。 DeepSeek以创新技术直击产业痛点,而博云先进算力管理平台AIOS的全面适配,则为这一技术…

ArcGIS Pro建库中常用公式的应用与技巧

在当今数字化的时代,地理信息系统(GIS)在各个领域都发挥着至关重要的作用。 ArcGIS Pro作为一款功能强大的GIS软件,为用户提供了丰富的工具和功能,使得数据处理、地图制作和空间分析变得更加高效和便捷。 本文将为您…

C++入门基础

文章目录 C核心特性详解(基础增强版)一、第一个C程序:Hello World完整代码解析新手常见问题 二、命名空间(详解版)1. 为什么需要命名空间?2. 命名空间使用场景3. 嵌套命名空间4. 匿名命名空间 三、输入输出…

探秘基带算法:从原理到5G时代的通信变革【三】Turbo 编解码

文章目录 2.2 Turbo 编解码2.2.1 基本概念与系统构成2.2.2 编码过程分步解析交织器递归系统卷积编码器复接器总结 2.2.3 译码算法分类与原理Turbo码的强大主要来源于其解码器理论基础解码过程详解交织与解交织译码算法总结 2.2.4 Turbo码的应用场景无线通信卫星通信深空通信 2.…

一键无损放大视频,让老旧画面重焕新生!

打工人们你们好!这里是摸鱼 特供版~ 嘿,朋友们!在数字时代,视频已经成为我们生活中不可或缺的一部分。无论是珍贵的家庭录像,还是老旧的影视素材,我们都希望能以高清画质重温那些美好瞬间。但很多时候&…

build gcc

1,下载源码 wget https://gcc.gnu.org/pub/gcc/infrastructure/mpfr-4.1.0.tar.bz2 wget https://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 wget https://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.2.1.tar.gz git clone --mirror https://github…

《用Python+PyGame开发双人生存游戏!源码解析+完整开发思路分享》

导语​ "你是否想过用Python开发一款可玩性高的双人合作游戏?本文将分享如何从零开始实现一款类《吸血鬼幸存者》的生存射击游戏!包含完整源码解析、角色系统设计、敌人AI逻辑等核心技术点,文末提供完整代码包下载!" 哈…

AutoGen学习笔记系列(一)Tutorial - Model

这个系列文章记录了学习微软 AutoGen 的过程,与 smolagents 学习笔记系列一样,仍然以官方教程自己的理解为主线,中间可能穿插几个番外支线的形式写博客。 【注意】:在阅读这篇文章之前需要确保已经按照其 Installation 小节完成必…

探秘基带算法:从原理到5G时代的通信变革【八】QAM 调制 / 解调

文章目录 2.7 QAM 调制 / 解调2.7.1 概述2.7.2 星座图星座图的结构与性能发射端的信息编码与接收端的解码差分编码的分类与实现差分编码的模4格雷加法器公式16QAM星座图与映射关系 2.7.3 信号表达式正交振幅调制的基本原理与系统分析相位误差对QAM性能的影响多电平正交振幅调制…

本地YARN集群部署

请先完成HDFS的前置部署,部署方式可查看:本地部署HDFS集群https://blog.csdn.net/m0_73641796/article/details/145998092?spm1001.2014.3001.5502 部署说明 组件配置文件启动进程备注Hadoop HDFS需修改 需启动: NameNode作为主节点 DataNode作为从节点 Secondary…