"程序是写给人读的,只是偶尔让计算机执行一下。—— Donald Knuth"
引言
随着前端应用的大型化和复杂化,越来越多的前端工程师和团队开始重视 JavaScript 代码规范。得益于前端开源社区的繁盛,当下已经有几种较为成熟的 JavaScript 代码规范检查工具,包括 JSLint、JSHint、ESLint、FECS 等等。EOS-JS,它是一款插件化的JavaScript 代码静态检查工具,具备全套的热修复、增量更新方案,集各类代码规范检查工具优势于一体,其核心是通过对代码解析得到的 AST(Abstract Syntax Tree,抽象语法树)进行模式匹配,定位不符合约定规范的代码、给出修改意见并支持一键修复,在降低维护成本、提升执行效率的同时,也保障了代码规范的统一。
为实现规范编码、提高编码质量,目前较为通用的是直接使用开源生态中提供的一些标准方案,可以用较低成本来实现 JavaScript 代码规范的落地。如果再搭配一些辅助工具(例如 husky 和 lint-staged),整个流程会更加顺畅。但是对于大型企业开发团队而言,数十人甚至上千人面对数万个工程,规模化地应用统一的 JavaScript 代码规范,并且有效落地执行,问题就会变得较为复杂。
痛点分析
设计初期,我们收集了大量前端开发人员的编码痛点,可以归纳为以下几点:
人员角度
公司部门团队较多,从上往下宣传,执行难度较大
团队(人员)风格差异大的,不是每个团队都自愿去梳理适用的规则集
没有数据统计和有效的监管方案,人员执行状况及编码优化成效没办法衡量
技术角度
- 技术选型分散, React、Vue、JavaScript、TypeScript 等
- 开发工具可选性多,Vscode、WebStorm等
- 工程量大,每个工程都按照开源方案进行配置,复杂度提升,管理混乱
解决方案
针对上文中提出的问题,我们设计了一套完整的技术解决档案,基于EOS-JS提供了插件端和平台端两种扫描方法,用户可结合实际情况自由选择。
EOS-JS是一个扫描引擎,通过基础检测能力和模式约束,推动代码检测流程的运转。原始代码经过解析器的解析,在管道中逐一经过所有规则的检查,最终检测出所有不符合规范的代码,并输出为报告。
整体设计方案分为以下几点:
- 定位问题与自动修复:该模块是整体方案的基石,通过解析代码得到AST,进行模式匹配,定位不符合约定规范的代码,并针对通用规范问题编码提供自动修复能力。
- 多场景通用规范(核心):通过分层分类的结构设计,在保证基础规则一致性的同时,实现了对不同场景、技术选型的支撑。
- 自动化接入升级:通过JD插件中心实现两端(Plugin/Server)“一键”接入,自动升级,极大降低了工程接入和维护的成本。
- 多端代码检测:该模块是方案落地执行的保障,将代码检查与本地实时编码及CI持续集成工作流程相结合。在保证代码集成质量的同时,也通过定制集成检查/修复工具降低了开发者的应用执行成本。
- 数据统计可视化:通过对工具运行和代码集成检查过程进行埋点、检查结果收集和分析,了解方案的应用状态和效果。
整体方案设计图如下所示:
具体实现
整体方案已确认,但具体到各个模块的实现,仍然需要进一步深入思考,以设计出更加合理的实现方案。本章将对方案的几大核心模块进行详细介绍。
01 定位问题、自动修复
代码解析,获取问题数据源是开发扫描引擎,统计编码问题的前提。
AST编译简介
AST:简单理解,就是把我们写的代码按照一定的规则转换成一种树形结构。在javascript世界中,可以认为抽象语法树(AST)是最底层, 再往下,就是关于转换和编译的“黑魔法”领域了。我们常见的前端开发插件javascript转译、代码压缩、css预处理器、pretiier等都建立在了AST这个巨人的肩膀上。EOS-JS引擎集百家之所长,基于AST抽象 JS 源码的共性,分析源码,进行模式匹配,检查问题。
编译流程主要分为以下四步:
- 词法分析scanner
- parser生成AST树
- traverse对AST树遍历,进行增删改查
- generator将更新后的AST转化成代码
可以很清楚的看出,实现代码扫描,可以在parser生成AST树后,进行模式匹配。实例演示如下:
insert函数解析后,得到如下所示结构体:
提出修改建议、一键修复。
实际编码过程中,我们充分利用AST优势针对常见编码规范问题例如:注释、代码替换等提供了一键修复能力,提高了开发者编码效率。继续以insert函数为例,基于我们前面得到的insert函数体的语法树分析,实现代码替换功能:
02 多场景通用规范
这一模块是整体方案的核心,采用分层分类的结构设计,提供多场景、多技术方案的通用配置方案,解决了用户最大的痛点,并使方案具备易维护、易扩展的特性。
详细配置方案如下:
EOS-JS扫描引擎借助插件化设计原理,与解析器解绑,我们可以使用不同的解析器进行原始代码解析,例如使用不同的解析器处理 ES 语法与TypeScript 语言。最终实现所有的规则可独立控制,并且具备自定义拓展能力。
动态配置化方案
EOS-JS提供了全面、灵活的配置能力,可以对解析器、规则、环境、全局变量等进行配置;还可以配置层叠、实现配置共享。具体的使用中,各团队可以根据部门需求灵活的选择各层级、各类型的搭配,在代码检测平台获得和项目匹配的规则集,如仍不满足需求,也可以通过自定义规则集,得到自己预期的统一规范工具。
Base层:通过公司内部前端开发团队制定统一的基础语法和格式规范,提供通用的代码风格和语法规则配置。
框架支撑层:提供对通用的一些技术场景、框架的支持,包括 Node.js、React、Vue、等;这一层借助多个团队对各种框架的规则使用建议,整合出适配各种框架的规则集。
TS层:这一层提供对TypeScript 的支持。扩展(自定义)层:针对团队的特殊规则诉求,提供定制化支持,目前已存在的JDSpecification便是为公司内部定制的前端代码扫描规范。
这种分层分类、配置解耦的设计结构,存在以下优势:
- 对Base层级的修改,影响全局。
- 对非基础层某一部分的调整不会产生关联性的影响。
- 如需扩展对某一类型的支持,团队通过自定义,配置完成后,只需关注这一类型的特殊规则配置。
该方案已在公司内部得到广泛使用,例如:Plus团队在平台配置自定义React规范,扫描该团队的React项目时规则即时生效,这种通过分层、分类的结构设计,节省了用户使用成本的同时,减少了规则维护成本,规则示例代码如下:
03 自动化接入升级
前端开发人员在开源方案的使用中经常遇到规则无效、兼容性、解析异常等问题,反复排查和定位问题会浪费大量的精力。因此在设计接入及升级流程时,我们充分考虑了规则集和工程方案的兼容性、用户使用场景、接入成本,操作体验等,采用了Plugin和Server可独立运行,亦可协同工作的设计模式。一键接入,自动升级,为用户带来良好的使用体验。工作流程如下图所示:
我们开发了JDPluginCenter插件,支持用户多场景需求,无论什么开发场景和框架选型,繁琐的接入流程都只需要用户安装JDPluginCenter或是一条命令集成到项目脚手架,便可实现在插件和平台两端的接入流程。
04多端代码检测
为避免因一些主观因素或疏漏造成的编码规范执行不到位,我们将代码规范静态检查与开发工作流集成,保证代码规范的有效落实。
本地开发实时检查: 本地编码过程中,EOS-VSCode插件有两种检查方式可供选择。实时检查编码问题给出修改建议,也可以针对单个文件、单个文件夹或者整个项目手动触发,开启检查流程,并将结果展示到前台。其优点在于实时性,可在编码过程中发现并解决编码规范及质量问题。
代码提交检查: 在代码 Commit 时,通过 gitHook 触发代码检查。其优点在于能实时响应开发者的动作,给出反馈,快速定位和修复问题 代码集成检查:在代码集成(借助 CI 系统的集成流程功能)时,通过代码检测平台对代码进行检查,检测不通过则阻断集成。其优点在于能够强制执行,可在线追踪检测报告。
Server端检查: 代码库源码或构建产物在服务端扫描。支持自动化定时扫描和用户主动触发扫描两种方式,其优点在于可以按照不同维度进行数据统计,对上可以有效监管,对下可以高效落实。
数据统计可视化
数据统计
核心是信息采集和分析。在本方案中:
- 执行状况监测:插件启动、关闭、用户信息、仓库地址等信息上报后,可精确分析使用率、扫描成功率、用户活跃度等。
- 扫描结果分析:插件端、CI持续集成节点、Server端扫描都会结果上报扫描结果,包括检查是否通过、blocker和warning信息的数量、问题代码段、问题代码行号等。
分析及数据可视化
该模块包含插件端可视化和平台可视化两部分:
- 插件端:实时检测,编码建议即时提醒;手动扫描,结果分析统计后展示到编辑器view,供开发人员直接定位问题代码行。
- 平台端:个人、团队、工程等各维度进行数据汇总,通过图形、报表多种类型进行数据展示及邮件通知。某团队编码问题变化趋势:
以上是京东零售技术与数据中心共享技术部在检查前端编码规范及编码质量过程中的一些实践,欢迎交流。
欢迎点击【京东科技】,了解开发者社区
更多精彩技术实践与独家干货解析
欢迎关注【京东科技开发者】公众号