在计算机科学和软件工程中,增量
一词通常指的是对系统、数据或过程的小幅度修改或增加。它可以应用于多个领域和上下文,包括但不限于软件开发、数据处理和系统更新。
以下是一些具体的应用场景,以帮助解释 增量
的概念:
-
在软件开发过程中,增量更新指的是对软件应用或系统进行的小规模更改,而不是一次性重写或全面更新。这种方法允许开发者逐步引入新功能或修复,从而减少对现有系统的干扰,同时也使得问题的追踪和修复更加容易。
-
在数据备份领域,增量备份是指仅备份自上次备份(无论是全备还是增量备份)以来发生变化的数据。这种方法相比全量备份可以节省时间和存储空间,因为它只处理变化的部分.
-
在编程中,增量编译是一种编译技术,只重新编译自上次编译以来已修改的源代码文件,而不是每次都重新编译整个项目。这可以大大加快编译过程,特别是对于大型项目。增量编译需要跟踪文件的依赖关系和修改状态,以确保所有受影响的部分都被正确地重新编译。
在前端开发工程化领域,本文将介绍用 增量
思想提升代码检查的速度,从而实现开发过程的效率提升。
增量检查代码
在前端中,我们经常使用 Eslint 做代码规范静态检查。随着前端工程化的发展,我们会将代码检查与开发工作流程集成,在代码提交前和代码交付前自动做 ESLint 检查。代码提交检查即在开发者每一次 commit 时通过 git hooks 触发 ESLint 检查,当工程代码量很大时开发者每一次提交代码甚至要等数分钟时间才能检查完。代码交付检查即借助持续集成流程,比如在 MR 时触发代码检查,这是会阻断 MR 的流程的,经常会出现这样一种情况,某个 MR 仅仅修改了一行代码,却要扫瞄整个项目,这会严重影响持续集成的效率。所以大部分情况下并不需要进行 ESLint 的全量扫描,我们更关心的是新增代码是否存在问题。
接下来我们通过自定义 git 的 pre-commit 钩子脚本来为一个工程实现增量代码提交检查能力。
查找到修改的文件
要在 git 的 pre-commit 钩子中找出被修改的文件(即即将被提交的文件),可以使用 git 命令结合脚本来实现。这里提供了一些方法和示例来帮助你找出修改的文件,并且可以将这些方法整合到 pre-commit 钩子中,以实现自动化的操作。
git diff 命令可以显示已修改但尚未暂存的文件之间的差异。结合特定的选项,你可以用它来列出被修改的文件。
列出已暂存(即将提交)的文件:
bash
git diff --cached --name-only --diff-filter=d
列出所有已修改的文件(包括已暂存和未暂存的):
bash
git diff --name-only --diff-filter=d
这里,--cached 选项意味着只考虑已暂存的文件,--name-only 则让 git diff 仅列出文件名,而不显示具体的差异内容,加 --diff-filter=d 参数是为了去掉被删除的文件,删除的文件不需要再做检查了。
对被修改的文件进行代码检查
ESLint 提供了同名类函数(ESLint)作为 Node.js API 调用,这样我们能在 node 脚本中执行代码检查并拿到检查结果。
要编写一个 Node.js 脚本,利用 git diff 检查出修改的文件然后使用 eslint 进行检验,你可以遵循以下步骤。这个脚本会使用 Node.js 的 child_process 模块来执行命令行指令,获取修改的文件列表,然后逐个对这些文件运行 eslint 检查。
js
const { execSync } = require("child_process");
// 获取git diff的结果,只包含修改和新增的文件
const getModifiedFiles = () => {
try {
const result = execSync("git diff --name-only --diff-filter=d", {
encoding: "utf-8",
});
return result
.split("\n")
.filter((diffFile) => /(\.ts|\.js)(\n|$)/gi.test(diffFile));
} catch (error) {
console.error("Error getting modified files:", error);
return [];
}
};
// 运行 ESLint 检查
const runEslint = (files) => {
if (files.length === 0) {
console.log("No JavaScript files to lint.");
return;
}
try {
execSync(`./node_modules/.bin/eslint ${files.join(" ")}`, {
stdio: "inherit",
});
console.log("Linting passed!");
} catch (error) {
console.error(
"Linting errors found. Please fix the errors and try committing again."
);
process.exit(1); // 退出脚本并返回错误状态
}
};
const modifiedFiles = getModifiedFiles();
runEslint(modifiedFiles);
如上代码,我们检测出了 /packages/core/src/index.ts
目录下的文件被修改了,很明显这个类型有错误的,所以执行该脚本就必然会报错的:
现在我们是需要手动的,这个时候我们就需要将其放在 pre-commit 钩子中执行该脚本了:
我们只需要在 husky 目录下的 pre-commit 文件添加以下代码即可:
sh
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo 'running pre-commiting checks ...'
node ./index.js
这样,在我们执行完成 commit 之前会执行该 sh 命令,也就说会执行 node ./index.js 这个命令,我们需要对脚本进行小改:
js
const result = execSync("git diff --name-only --cached --diff-filter=d", {
encoding: "utf-8",
});
这是因为当我们执行到这一个步骤时,之前修改的代码都存放到了暂存区了,所以要添加 --cached
这一行指令。
这个时候当我们执行 commit 的时候,会有如下输出:
这也正是我们之前编写的 var 声明的变量导致的报错,如果检查到错误,就以非 0 值退出,git 将放弃本次提交。
最终实现的效果是开发者在提交代码时再也不用等待全量代码检查完成了,脚本会很快找到有改动的文件并检查完。
总结
通过 git diff
找出变更的文件,实现增量代码检查,避免全局检查代码,可以极大地提升我们开发的效率。
除了在 pre-commit 这个钩子上实行这个逻辑,我们也可以在 ci 上实现,只要我们找出本次变更的代码即可。这里只提供一个参考。
最后分享两个我的两个开源项目,它们分别是:
这两个项目都会一直维护的,如果你也喜欢,欢迎 star 🚗🚗🚗