如何根据文件最后修改时间配置ESLint,灵活纳入或排除待校验文件
大型遗留代码库按文件修改时间粒度落地ESLint的实现方案
原生扩展点能力说明
ESLint 8.x 正式推出的**Flat Config(扁平配置)**提供了原生的自定义文件过滤扩展点,完全可以实现基于文件最后修改时间的校验范围判断,不需要依赖动态生成.eslintignore的临时方案,也不需要强制使用第三方插件。
注意:如果当前项目仍在使用ESLint 7及更早的版本,不支持Flat Config的自定义filter能力,要么先升级ESLint版本,要么直接使用下文提到的第三方插件方案。
这个扩展点的核心逻辑是:Flat Config本身是纯JavaScript模块,ESLint在扫描待校验文件时,会调用配置中定义的filter回调函数,传入当前扫描到的文件绝对路径,由用户自己编写逻辑判断该文件是否需要被纳入校验范围,完全适配“仅校验推广节点后修改的文件”的需求。
无依赖原生实现步骤
- 在项目根目录新建
eslint.config.js配置文件(替代旧版的.eslintrc配置格式) - 定义固定的推广节点时间阈值,所有最后修改时间晚于该节点的文件才会被校验
- 在配置的
filter回调中,通过Node.js内置API读取文件的修改时间,和阈值做对比,返回判断结果即可
核心参考逻辑:
// eslint.config.js const fs = require('fs'); // 定义ESLint正式推广的时间节点,可根据实际项目调整 const ROLLOUT_CUTOFF = new Date('2024-05-20T00:00:00').getTime(); module.exports = [ { // 全局基础ESLint规则 rules: { // 按项目需要配置规则内容 }, files: ['**/*.js'], // 匹配需要扫描的文件类型 // 自定义文件过滤逻辑 filter: (filePath) => { try { // 读取目标文件的最后修改时间(毫秒级时间戳) const fileMtime = fs.statSync(filePath).mtimeMs; // 仅保留修改时间晚于推广节点的文件 return fileMtime > ROLLOUT_CUTOFF; } catch (err) { // 文件读取异常时直接跳过该校验 return false; } } } ]
常见坑点提示
直接读取文件系统的mtime很容易出现稳定性问题:
- 执行
git checkout切换分支、用同步工具拉取文件、调整文件权限操作时,文件的mtime会被意外刷新,导致本应豁免的旧代码被纳入校验 - 团队协作时不同成员本地的文件mtime没有统一标准,经常出现“本地跑lint全部通过、CI跑就触发一堆存量报错”的情况
如果需要更稳定的判断逻辑,可以把filter中的文件系统读取逻辑替换为读取git仓库中该文件的最后提交时间戳,和推广节点做对比——这种方式不受本地文件状态影响,所有团队成员跑出来的校验规则是完全一致的。
现成第三方插件方案
如果不想自己编写基础的文件判断逻辑,可以直接使用成熟的现成工具:
eslint-plugin-filter-by-mtime:专门适配mtime过滤场景的插件,在配置中引入后可直接定义时间阈值,内置了文件系统mtime、git提交时间两种判断模式,不需要重复编写fs读取逻辑eslint-rollout:针对遗留代码库渐进式接入ESLint场景开发的工具,内置了时间阈值过滤、存量代码自动豁免、新增代码强制校验的全流程能力,不需要自行维护复杂的判断规则
注意不要和
lint-staged、eslint-watch这类工具混淆:这类工具仅针对工作流触发时机做过滤(比如只校验暂存区文件、只校验当前本地修改的文件),不支持自定义固定时间节点的长期校验规则,不适合渐进式推广场景。
对比动态生成.eslintignore方案的优势
传统动态生成ignore的方案需要在每次执行ESLint前,先运行前置脚本全量扫描所有文件的修改时间,把早于推广节点的文件写入.eslintignore文件,这种方案的缺陷包括:
- 需要维护独立的前置执行脚本,容易出现脚本执行顺序错误、ignore文件未更新导致的校验范围异常
- 全量文件扫描的前置过程存在额外的性能开销
- 过滤逻辑和ESLint配置分离,长期维护容易出现规则不一致
而基于Flat Config扩展点的实现方案,过滤逻辑是ESLint原生扫描流程的一部分,不需要额外前置步骤,所有规则集中在配置文件中维护,扫描过程中不会产生重复的文件遍历开销,长期维护成本更低。
内容的提问来源于stack exchange,提问作者Ken
相关产品推荐
相关产品推荐

