一款检测代码中TODO的eslint插件|项目复盘

简介: 一款检测代码中TODO的eslint插件|项目复盘

前言


看了我标题进来的同学应该也知道我做的是个啥东西


没错是一个eslint插件,前端魔法师们日常所使用的工具之一


什么?你不知道eslint是干嘛的--吃鲸.jpg


  • ESLint 是一个开源的 JavaScript 代码检查工具
  • 能在多人协作项目中帮助统一代码风格


百闻不如一见,先带大家看看插件效果


网络异常,图片无法展示
|


因为在工作中临时会插入许多其它的事,或者有些代码,接口是有时效性的需要手动下线

插件功能简单讲就是为不完善的代码做标记,提醒自己如期修改完善bug


想亲自尝试一下的同学戳这里---顺手Star


下面开始介绍为什么会写这个插件,以及过程中遇到的问题,和插件的一些核心方法


背景


前端魔法师们,经常不经意间就会在代码中下毒,坑害同事,甚至直接使"线上爆炸"

当时遇到一个线上问题就是如此:


  • 一个有实效性的活动入口,需要到点下线,一个需要常驻的活动入口,不需要下线
  • 由于实效性活动下线时间还有大半年


coder为了图方便,直接把实效性活动业务组件拿着复用,想着到时候改,反正时间还长

半年后的一天,客述就来了,说xx入口怎么不见了,彼时开发此页面的同事已经调走,目前的项目组基本都是后来的


第一反应是不是昨晚提交了什么代码,把入口吓掉了,然后就开始翻发布记录,发现并没有发版,就奇怪了,好好地怎么就不见了


然后同事们就开始排查代码了,不一会儿就发现了问题所在,然后快速的改掉上线,避免影响扩大


事后复盘


  • Leader: 咱能不能用啥工具避免此类问题发生
  • 菜鸡: 阿巴阿巴一堆话
  • Leader: 那行你说了这么多,这个任务就交给你了,下周给个方案
  • 菜鸡: ...哦豁,要被卷铺盖走人了


个人思考


在不完善的代码或有时效性的代码处搞一个flag,通过工具检测这个flag然后提醒此项目的所有开发者


开发者打开这个项目就能知道xx flag处有隐患


调研-可行方案


cli工具


项目启动后,跑一个npm script

扫描目标文件,然后通过正则匹配flag关键字基于提示


vs code插件


前端魔法师基本都用的Vs Code

项目启动后,自动扫描目标文件

通过正则匹配flag,然后基于提示

这个有现成的todo-tree


eslint规则


前端项目都会引入eslint 来统一团队成员的编码风格


只要编写一个自定义的规则,通过分析eslint 提供的AST,就能轻易的拿到标记的flag


对比


方案 优点 缺点 学习成本
cli工具 不限制语言/文件类型,通过正则就能进行轻易的匹配 需要为每个项目单独编写一个指令,通过hook或者人工触发 ❤❤❤
vs code插件 只需要用户为编辑器安装一个插件,即可在打开的时候进行提示 魔法师们可能用sublime/webStorm ,需要重复开发插件 ❤❤❤❤
eslint规则 只需要在项目的配置文件中加入一行规则代码,即可实时的提示 需要安装依赖,首次需要手动引入 ❤❤


最终选择


基于eslint编写一个eslint-plugin来实现自定义校验规则


原因


  • 前端项目都会引入eslint
  • 不限制编辑器
  • 理论上不限制前端开发常用的语言/框架的检测
  • 标准化团队统一了所有仓库的lint规则,只需在标准化规则中加入即可
  • 其余仓库,只要执行依赖安装(yarn/npm i) 就会将最新的规则引入项目,使用者能0配置接入


实现过程


下面会展开介绍插件的实现原理,会涉及到一些代码的展示


首先eslint会将响应的文件用AST描述出来,并且提供了一些简单的API进行操作


create(context) {
    // 取得AST
    const sourceCode = context.getSourceCode()
    // 获取所有的注释节点
    let comments = sourceCode.getAllComments()
}


注释节点有两种


// 注释
/** 
 * Block
 **/


从注释节点中过滤出以flag关键字开始的注释节点


// 过滤出包含关键词的注释节点
comments = comments.filter(comment => {
    let { value, type } = comment
    // 展平块状注释
    if (type === 'Block') {
        value = value.replace(/\*|\n/g, '')
    }
    value = value.toLowerCase().trim()
    // 保存格式化后的字符串
    comment.newValue = value
    for (const flag of dFlag) {
        // 检测是否一关键字开头
        if (value.startsWith(flag)) {
            // 保存上flag
            comment.flag = flag
            return true
        }
    }
    return false
})


此时过滤后的注释基本格式如下


// flag ddl:time  xxxxx


接下来从中解析出ddl和提示信息


首先ddl也是一个可配置的关键字


需要检测的日期格式如下


format1 demo format2 demo format3 demo
yyyy-mm-dd 2020-06-01 yyyy/mm/dd 2020/06/01 yyyymmdd 20200601
2020-06-1 2020/06/1 200601
2020-6-01 2020/6/01
20-06-01 20/06/01
20-6-1 20/6/1
20-6-01 20/6/01


所以代码中做了许多判断


  • 代码可能有点shi,看官们可以给点建议优化下


// 匹配日期的正则
const rDate = [{
    reg: /((\d{4})|(\d{2}))(-((0\d)|(\d{2})|(\d{1}))){2}/,
    flag: '-' // yyyy-mm-dd|yy-mm-dd
},
{
    reg: /((\d{4})|(\d{2}))(\/((0\d)|(\d{2})|(\d{1}))){2}/,
    flag: '/'// yyyy/mm/dd|yy/mm/dd
},
{
    reg: /(\d{8})|(\d{6})/,
    flag: 'number'// yyyymmdd|yymmdd
}]
/**
 * 获取TODO注释中的DDL,是则返回日期值及其todo内容
 * @param {String} value 待操作字符串
 * @param {String[]} ddlSymbol 截止时间标识符
 * @param {STring} todoSymbol
 * @return {Object} 
 */
function getDDLAndText(value, ddlSymbol, todoSymbol) {
    let text = value.slice(value.indexOf(ddlSymbol) + ddlSymbol.length),
        date = ''
    for (const rdate of rDate) {
        const { reg, flag } = rdate
        const res = text.match(reg)
        if (res) {
            const [dateStr] = res
            // 再次校验匹配的日期日期是否合法
            if (reg.test(dateStr)) {
                let year, month, day
                if (flag !== 'number') {
                    let ymd = dateStr.split(flag)
                    ymd = ymd.map(v => {
                        return v.length === 1 ? `0${v}` : v
                    })
                    year = ymd[0]
                    month = ymd[1]
                    day = ymd[2]
                } else {
                    const { length } = dateStr
                    day = dateStr.slice(length - 2)
                    month = dateStr.slice(length - 4, length - 2)
                    year = dateStr.slice(0, length - 4)
                }
                if (year.length === 2) {
                    year = new Date().getFullYear().toString().slice(0, 2) + year
                }
                text = text.slice(text.indexOf(dateStr) + dateStr.length)
                date = `${year}-${month}-${day}`
                // 日期不合格也pass掉
                if (month > 12 || day > 31) {
                    date = ''
                }
                break
            }
        }
    }
    return {
        text,
        date
    }
}


这样就拿到了flag的截止日期内容


接下来只需要根据设置的时间警戒线进行提示即可


// 未设置DDL或者DDL不合法情况
if (!date) {
    errMsg = '没有设置有效的Deadline,设置方法(https://github.com/ATQQ/eslint-plugin-todo-ddl)'
} else {
    const TODODate = new Date(date).getTime()
    const interval = TODODate - Date.now()
    // 如果已经到期
    if (interval < 0 || interval < oneDay) {
        errMsg = '已经过截止日期,请立即修改'
    } else {
        // 剩余天数(向下取整)
        const theRestDays = ~~(interval / oneDay)
        errMsg = theRestDays <= dWarnLine ? `还有${theRestDays}天截止,请尽快修改` : ''
    }
}
if (errMsg) {
    context.report({
        node: comment,
        message: `TODO WARN: ${errMsg} --> ${text}`
    })
}


到此就大工搞成了,可以发包上线了


总结思考


不足之处


  1. 代码还有可改进之处
  2. 插件上线后并没大改过,功能感觉还可以增强,需要朋友们多给点意见


收获


  1. leader还是评价不错,毕竟那时候实习生身份刚入职几天
  2. 自己也有所提升,对eslint的工作原理有了新的认识
  3. 也为团队日后各种花式校验规则提供了技术积累


未来


  1. 找时间根据反馈,迭代一下插件,提高其可玩性


其它


相关文章
|
JavaScript 应用服务中间件 nginx
vuecli3打包项目上线之后报错怎么使用本地的sourcemap文件定位调试?
vuecli3打包项目上线之后报错怎么使用本地的sourcemap文件定位调试?
195 0
|
2月前
|
移动开发 Unix Linux
拉取代码编辑器中报错`Delete ␍ prettier/prettier` 问题的解决方案
通过正确配置Prettier、EditorConfig文件和编辑器设置,可以有效解决 `Delete ␍ prettier/prettier`的问题。这不仅能避免频繁的格式化错误,还能确保团队成员在不同开发环境下的代码风格一致,提升项目的代码质量和可维护性。按照上述解决方案调整配置后,您的项目将更加规范,代码也会更具一致性。
109 4
|
2月前
|
JavaScript 测试技术 开发者
确定 Babel 插件的功能是否符合项目需求
【10月更文挑战第25天】细致的评估方法,可以较为准确地确定 Babel 插件的功能是否真正符合项目需求,从而为项目选择合适的插件,保障项目的顺利开发和高质量交付。
|
3月前
|
JavaScript 前端开发 开发者
如何在 VSCode 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升团队协作效率和代码质量。
【10月更文挑战第9天】随着前端开发技术的发展,代码规范和格式化工具变得至关重要。本文介绍如何在 VSCode 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升团队协作效率和代码质量。通过安装插件、配置 ESLint 和 Prettier,以及设置 VSCode,实现代码实时检查和格式化,确保代码风格一致。
584 2
|
JavaScript 前端开发
在VSCode中 使用 ESLint + Prettier检查代码规范及自动格式化前端Vue代码
般的代码格式化工作,ESLint完全可以胜任,为什么要用Prettier代替ESLint的代码格式化功能?简而言之,Prettier的代码格式化功能比ESLint更强大,配置更简单,通过配置,ESLint可以使用Prettier的代码规则进行校验,如果不配置好,会出现冲突,导致二者不能配合使用。 下面详细介绍如何配置ESLint+Prettier在VSCode中开发Vue代码:
1417 29
在VSCode中 使用 ESLint + Prettier检查代码规范及自动格式化前端Vue代码
|
3月前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升代码质量和团队协作效率。
【10月更文挑战第8天】本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查并自动格式化 Vue.js 代码,提升代码质量和团队协作效率。通过安装 VSCode 插件、配置 ESLint 和 Prettier,实现代码规范检查和自动格式化,确保代码风格一致,提高可读性和维护性。
124 2
|
4月前
|
前端开发 JavaScript 开发工具
前端项目增加eslint全过程
如何在前端项目中安装并配置ESLint和Prettier,包括VSCode插件的安装、npm包的全局安装、.eslintrc.js配置文件的生成以及编辑器设置的调整。
66 6
|
5月前
|
开发工具 git
emo——给项目配置prettier,eslint,husky加强协作规范
emo——给项目配置prettier,eslint,husky加强协作规范
61 2
|
7月前
|
IDE 前端开发 JavaScript
Prettier与ESLint:代码风格与质量的自动化保证
这两个工具协同工作以确保代码一致性。Prettier负责自动格式化,包括缩进、引号等,而ESLint执行静态分析,检查潜在错误和风格。Prettier配置文件如`.prettierrc`,ESLint配置如`.eslintrc.js`。安装它们并集成,例如使用`eslint-plugin-prettier`和`eslint-config-prettier`。在提交前,可通过husky和lint-staged在本地自动运行格式化和检查。IDE中配置插件可实现实时反馈。自定义规则和选择共享配置(如airbnb)以适应项目需求,并在CI流程中集成以保持高标准。
99 1
|
8月前
|
开发者
Eslint插件使用配置, 规范化开发, 详细配置流程
Eslint插件使用配置, 规范化开发, 详细配置流程