一个项目运行久了,中间又经过开发人员的更替,常常会导致项目代码臃肿,重复率增高,后面想要优化也变得难上加难,同时多个项目间也会出现代码复制粘帖的情况,这种问题其实是可以通过工具检测和统计出来的。最近逛社区发现了一个检测代码重复率的纯JavaScript代码库【jscpd】,于是自己在本地跑了几遍,还不错,在这里记录分享一下~
jscpd介绍
- 根据Rabin-Karp算法实现代码重复率的搜索。
- 支持150多种编程语言源码文件格式(包括各种前端框架,vue、react等)。
- 支持输出多种文档形式的检测报告,比如:html、json、markdown等。
- 开源地址仓库:github.com/kucherenko/jscpd/tree/master
jscpd使用
1、安装
两种安装方式,根据自身条件选择即可
// npm方式
npm install -g jscpd
// yarn方式
yarn global add jscpd
2、使用示例
- 单个文件检测
jscpd ./custom-select.vue
- 文件夹检测
jscpd ./src
命令执行完成后,会生成一个检测报告表格,如下:
- 字段介绍
-
Format: 文件格式,例如 javascript、scss、markup、css等。
-
Files analyzed: 分析的文件数量,可以统计项目中文件数量。
-
Total lines: 被分析的所有文件中的代码总行数。
-
Total tokens: 所有token的数量,一般以
标识符/变量等、数字、字符串、空格或符号等等作为一个token来统计数量。一行代码一般包含几个到几十个不等的token数量。 -
Clones found: 查找到拷贝的重复代码块数量
-
Duplicated lines: 重复的行数及占比,
占比 = 重复行数 / 总行数 * 100,这里以markup为例:30873(重复行数)/206720(总行数) = 0.149346。 -
Duplicated tokens: 重复的token数量及占比。占比计算公式与上面的
Duplicated lines一样,这里就不举例了。 -
Found N clones: 共检测到N个重复块,示例显示为1185。
-
Detection time: 检测耗时,示例本次耗时20.564秒。
根据上面的检测结果介绍,可以初步了解jscpd的一些基本知识,接下来说一下如何在项目中配置jscpd。
3、单个项目中配置jscpd
下面的代码来自@jscpd/core,可以看到jscpd提供的配置项。
export function getDefaultOptions(): IOptions {
return {
executionId: new Date().toISOString(),
path: [process.cwd()],
mode: getModeHandler('mild'),
minLines: 5,
maxLines: 1000,
maxSize: '100kb',
minTokens: 50,
output: './report',
reporters: ['console'],
ignore: [],
threshold: undefined,
formatsExts: {},
debug: false,
silent: false,
blame: false,
cache: true,
absolute: false,
noSymlinks: false,
skipLocal: false,
ignoreCase: false,
gitignore: false,
reportersOptions: {},
exitCode: 0,
};
}
以下是一些常用的配置项介绍
| 配置项 | 功能 | 默认值 | 类型 |
|---|---|---|---|
| minLines | 最小代码行数 | 5 | number |
| maxLines | 最大代码行数 | 1000 | number |
| maxSize | 最大文件大小,单位为kb | 100 | string |
| minTokens | 代码的最小块大小。代码块小于设置的min-tokens将被跳过 | 50 | number |
| output | 检测完成后,文件输出目录 | ./report | string |
| reporters | 输出类型,比如:markdown、html、json、xml、csv等 | console | array |
| ignore | 检测是想要忽略的文件目录或文件,用于过滤一些非业务代码,如依赖包、构建或静态文件等 | [] | array |
| threshold | 重复率阈值 | undefined | [number,undefined] |
| absolute | 在检测报告中是否使用绝对路径 | false | boolean |
| gitignore | 最小代码行数 | 5 | |
| formatsExts | 设置自定义扩展名的文件 | {} | object |
| silent | 是否打印更多关于检测过程中的信息 | false | boolean |
| cache | 缓存 | true | boolean |
3.1 jscpd提供两种配置方式
- 项目根目录下创建配置文件
.jscpd.json,在此文件中配置具体参数。
// .jscpd.json
{
"threshold": 0.1,
"reporters": [
"html",
"console"
],
"ignore": [
"node_modules",
".npmrc"
],
"absolute": true
}
- 直接在
package.json文件中添加配置项,项目中没有package.json,可以自行添加一个。
// package.json
{
...
"jscpd": {
"threshold": 1,
"reporters": [
"html",
"console"
],
"ignore": [
"node_modules",
".npmrc"
],
"absolute": true,
"gitignore": true
}
...
}
以上两种方式选择任意一种配置完成后,执行对应的命令即可输出报告。
这里以上面的package.json文件中的配置为示例,执行下面的命令
jscpd ./src
jscpd会根据package.json文件中的配置项检测当前项目下src目录下的所有文件,阈值为1,检测完成后,会在项目根目录下生成一个report目录,里面存放输出报告,报告的类型为html格式。
下面是命令执行完成后生成的检测报告目录:
在浏览器中打开index.html,显示的内容如下:
此外,也可以在scripts中配置运行脚本命令:
"scripts": {
"jscpd": "jscpd ./src"
}
3.2 命令行方式检测
有些时候,可能不需要针对整个项目进行检测,想要检测几个文件间的代码重复度,这种情况下,可以不用配置jscpd的配置文件,直接在命令行输入对应的简易命令即可。
例如:
jscpd ./src --min-tokens 20 --min-lines 20 --max-lines 2000 -o 'report' -r html
// 简写方式
jscpd ./src -k 200 -l 10 -x 2000 -o 'report' -r html
- 最小tokens:
--min-tokens,简写-k。 - 最小行数:
--min-lines,简写-l。 - 最大行数:
--max-lines,简写-x。 - 输出类型:
--reporters,简写-r。
4、多个项目配置jscpd
还有一种场景,就是检测多个项目间代码重复度,是否存在复制粘贴代码的现象。
针对这种场景,只需要在多个项目上级目录下配置一个package.json即可,额外需要注意的是,在配置文件中 ignore 属性的忽略目录,需要带上各项目的项目名称。
4.1 示例
- 目录如下:
test-jscpd目录下存在四个以xc-为前缀的项目,在目录下创建一个package.json文件
- 配置
package.json文件如下:
"jscpd": {
"threshold": 1,
"silent": true,
"minLines": 20,
"reporters": [
"html",
"console"
],
"ignore": [
"xc-rate/node_modules",
"xc-test-122/node_modules",
"xc-test-xcm01/node_modules",
"xc-test-xcm03/node_modules",
"xc-rate/package.json",
"xc-test-122/package.json",
"xc-test-xcm01/package.json",
"xc-test-xcm03/package.json"
],
"absolute": true,
"gitignore": true
}
- 执行命令
jscpd -o 'report' -r html
- 输出报告
jscpd自动创建一个名为report的文件夹,里面的检测报告为html类型,如下图:
在浏览器中打开index.html文件,内容如下:
5、忽略检测
很多时候,项目中有些重复的代码是必要的,而上面说的ignore属性中忽略某个文件或者文件夹已经无法满足需求了,此时可以使用注释代码标识的方式来忽略检测,在代码的首尾位置添加注释,jscpd:ignore-start 和 jscpd:ignore-end 包裹代码即可。
- 在js中使用
/* jscpd:ignore-start */
import XEUtils from 'xe-utils';
import { User } from './common';
import Api from './api.js';
/* jscpd:ignore-end */
- 在css以及各种预处理中使用
/* jscpd:ignore-start */
.bottom-operation {
box-sizing: border-box;
position: absolute;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
bottom: 0;
left: 0;
width: 100%;
min-height: 80px;
background: #fff;
border-radius: 4px 4px 0 0;
z-index: 999;
}
/* jscpd:ignore-end */
- 在html中使用
<!-- // jscpd:ignore-start -->
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<!-- // jscpd:ignore-end -->
以上就是全部内容了,有错误的地方欢迎掘友们纠正~