如何有效利用ESLint处理前端Sonar Issues问题

2,910 阅读8分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

背景

之前公司几个项目都配置了Sonar扫描平台,扫出来了很多Code规范问题,发文记录下解决此类问题的心得。

Sonar是一个开源平台,用于管理源代码的质量。一般用于扫描一个项目中所有代码的质量、规范、漏洞等问题。官网:www.sonarsource.com

想扫描代码得配置Sonar环境,一般分为SonarQubeSonarCloud,具体怎么配置笔者没用研究过,公司用到的是打包部门已经配置好的环境,配置上对应项目的git地址等,就可以做到自动化clone git、扫描、出report等。

以一个官方的项目为例:sonarcloud.io/project/ove… ,这是一个vscode-python项目的SonarCloud扫描结果report,点开Main Branch -> Issues会显示当前代码中被扫出来的问题,包括文件名、哪行出错、Rule规则等,也可以根据 TypeSeverityLanguageRule 来过滤。

image.png

然后项目开发这边就可以根据report来修复issues,分为以下三类:

  • Bug:可能会导致bug的Code。
  • Vulnerability:存在安全隐患,一般是第三方版本过低或存在漏洞等。
  • Code Smell:指可疑的Issues,不规范的代码。这主要是一个和维护性相关的指标,重点的含义是保持这样的代码,会导致代码维护成本越来越高,时间长了会导致很多无法理解的代码留存在项目中,从而可能会引起一些缺陷。

前两个Bug Vulnerability优先级比较高,如果一个项目的Issues过多,一般选择只修复这两种优先级高的Issues。

跟前端相关的Sonar rules大概有以下这些,具体还得看对应SonarQubeSonarCloud项目中配置了哪些Rules

点击对应Rule可以查看TypeLevel、详细规则等。 image.png

本文主要是以开发角度,来通过一些辅助工具提前解决前端code相关Issues,有效降低后期处理Sonar issues带来的开发维护成本。

关于Sonar环境安装、部署、配置、扫描等应该是打包或者运维部门的工作,此文不涉及。也不会具体分析每个Rule怎么改,大部分规则都很简单,仔细看下都能看懂。

通过ESLint来修复Sonar issues

ESLint 是一个开源的 JavaScript 代码检查工具,用来检查你的代码是否符合指定的规范。可以配合VSCode等IDE插件自动扫描提示,方便在写code过程中发现,有些Rules也支持autofix,可以在保存文件时自动修复。

关于ESLint详细用法,会在下一篇文章里讲解,包括指令、autofix、结合git commit等等。

Sonar扫描其实也是官方列出了一些 Rules,然后个人或者公司把这些Rules配置在自己的SonarQubeSonarCloud项目里,其中有很多Rules是跟ESLint官方Rules是等价的,也有些可以通过Sonar官方出的eslint-plugin-sonarjs来扫描。

下面主要介绍ESLint中哪些Rules可以用来替代sonar对应Rules,以便更好更快的修复Sonar问题。本文主要以笔者做过的相关项目为例,列举一些经常被扫出来的Rules,相关项目都是React框架、JS语言开发(没用Typescript)。

ESLint官方Rules

ESLint官方Rules:中文 | 官方

配置ESLint时,一般会启用推荐的规则 "extends": "eslint:recommended",即文档中标记✅号的Rules。里面有些Rules包含了Sonar rules,建议启用,这里就不具体查哪些Rules了。

有些不在recommended推荐规则里的Rules,需要手动将对应Rules配置在项目.eslintrc.js里,具体总结在下面:

  1. eslint: no-unused-vars

    • "no-unused-vars": ["error", { "args": "none", "caughtErrors": "none", "ignoreRestSiblings": true, "vars": "all" }]
    • 禁止未使用过的变量。删除未使用过的变量,暂不限制方法参数。
    • sonar rule: Unused assignments should be removed
    • Type: Code Smell Level: Major
    • 开发前期有些变量可能留着还有用,可以先设置为warn,然后后期再设置为error,即强制修复。
  2. eslint: array-callback-return

  3. eslint: no-unused-expressions

  4. eslint: default-param-last

  5. eslint: radix

  6. eslint: eqeqeq

  7. eslint: eol-last

  8. eslint: guard-for-in

    • "guard-for-in": "error"
    • sonar rule: 记得有这个Rule,link找不到了

eslint-plugin-sonarjs

SonarSource官方出的eslint plugin插件,内部封装了一些ESLint自定义Rules,文档:github.com/SonarSource…

用法很简单:

  1. npm install eslint-plugin-sonarjs --save-dev
  2. .eslintrc.js文件中添加plugin { "plugins": ["sonarjs"] }
  3. 配置"extends": ["plugin:sonarjs/recommended"],或者具体Rules。

推荐的recommended中几乎包含了sonarjs plugin中所有的rules,除了两个标记disabled的rule。如果你想严格规范所有的Rules,可以配置recommended;但如果只想对于其中一部分严重的Rules进行处理,建议不用recommended,自行配置具体Rules。下面举例比较常见的、严重的Rules:

  1. sonarjs: sonarjs/no-all-duplicated-branches

  2. sonarjs: sonarjs/no-identical-expressions

  3. sonarjs: sonarjs/no-extra-arguments

  4. sonarjs: sonarjs/no-use-of-empty-return-value

  5. sonarjs: sonarjs/no-collapsible-if

  6. sonarjs: sonarjs/no-duplicated-branches

  7. sonarjs: 其它不常遇到rules:Bug Detection 🐛 中列举的所有Bug类型的Rules。

其它

eslint-config-sonar

github.com/penx/eslint…

一个封装好的eslint config extends,内部利用no-wildcard-postmessage filenames sonarjs三个plugin,然后配置对应具体的Rules,来解决Sonar issues。

思路跟上面一样,但是更具体详细些,不过Star比较少,建议可以用来参考。具体Rules:github.com/penx/eslint…

SonarLint

官方提供的IDE插件,大多IDE都支持 www.sonarsource.com/products/so…

尝试用了下VSCode的插件,可以正确在Code里识别出来error(安装后反应会慢一些,稍等一会就会出来),也可以打开对应Rule详情,跟ESLint插件很像,但是没找到像ESLint那样可以通过指令扫描整个项目的功能,也不支持通过配置文件配置具体Rules,虽然可以通过extension settings配置,但只能在global下设置,不能设置在workspace下,就不能规范整个项目团队了。可能其它IDE支持的更好,或者是我哪块没用明白,有需要的可以试试。

image.png

插件还有个功能,可以通过配置连接自己SonarQubeSonarCloud项目的信息,然后插件会把项目里的配置、rules和issues等同步到VSCode里,具体没试过。

总结

本文主要介绍了如何利用ESLint快速高效解决Sonar Issues,如何有效降低后期处理Sonar issues带来的开发维护成本。

一般步骤如下:

  1. 首先看Sonar扫描的情况,如果Issues较多,可以优先解决Bug Vulnerability两种isues,Code Smell可以根据Rule尽量减小个数。
  2. 然后根据扫描出来的Rules,来配置针对性的ESLint rules,然后让开发团队保证自己的Code没有ESLint error
  3. 同时分析无法通过ESLint扫描的issues,可以团队内部制定相关Code规范,执行下去。
  4. 以上执行差不多时,再看下剩余的issues,此时个数不会太多,而且都是比较分散的,然后针对性的采取assign to的方式把task分下去依次解决。

通过笔者最近做过的项目来看,ESLint能覆盖大概90%的Sonar issues,效果还是很可观的,并且ESLint rules一旦配置好了,之后的项目开发和维护时,会很好的稳定Sonar issues数量,不会出现突然较多issues产生的情况。

另外,有些项目SonarQubereport中,集成了Dependency-Check功能,会扫出来有些第三方文件或者npm包的version漏洞问题(笔者就有,不确定是否跟Sonar有关)这个会在之后文章里讲解。

Code

最后share下项目里ESLint配置源码:

// .eslintrc.js
module.exports = {
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended"
  ],
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 13,
    "sourceType": "module"
  },
  "plugins": [
    "react",
    "sonarjs"
  ],
  "settings": {
    react: {
      version: "18.x"
    }
  },
  "globals": {
  },
  "rules": {
    // eslint rules for sonar
    "no-unused-vars": ["error", { "args": "none", "caughtErrors": "none", "ignoreRestSiblings": true, "vars": "all" }],
    "array-callback-return": ["error", { "allowImplicit": false, "checkForEach": false }],
    "no-unused-expressions": ["error", { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }],
    "default-param-last": "error",
    "radix": "error",
    "eqeqeq": ["error", "always", { "null": "ignore" }],
    "eol-last": "error",
    "guard-for-in": "error",

    // sonarjs plugin 目前配置的是所有支持的Bug类型Rules:https://github.com/SonarSource/eslint-plugin-sonarjs
    "sonarjs/no-all-duplicated-branches": "error",
    "sonarjs/no-element-overwrite": "error",
    "sonarjs/no-empty-collection": "error",
    "sonarjs/no-extra-arguments": "error",
    "sonarjs/no-identical-conditions": "error",
    "sonarjs/no-identical-expressions": "error",
    "sonarjs/no-ignored-return": "error",
    "sonarjs/no-use-of-empty-return-value": "error",
    "sonarjs/non-existent-operator": "error",
    "sonarjs/no-collapsible-if": "error",
    "sonarjs/no-duplicated-branches": "error",
    // "sonarjs/no-one-iteration-loop": "error", // 加上后eslint scan就抛错了,原因未知
  }
};