ESLint配置实战:从零搭建规范可靠的前端代码检查体系

小弯弯 前端 阅读 2,830
赞 12 收藏
二维码
手机扫码查看
反馈

优化前:卡得不行

上周我打开一个老项目,跑了个 npm run lint,结果终端直接卡住,风扇狂转,等了快5秒才出结果。平时改一行代码,编辑器里的 ESLint 插件也跟着卡半天,光标都跳不动。我一度以为是电脑老化了,直到在同事机器上试了下——同样卡成PPT。

ESLint配置实战:从零搭建规范可靠的前端代码检查体系

这项目其实不算大,也就二十来个页面,但 ESLint 配置是从三年前一路继承下来的,中间加过 Prettier、Airbnb、TypeScript 支持,还塞了一堆自定义规则。没人敢动,因为“能跑就行”。但这次实在忍不了了,决定花点时间优化一下。

找到瓶颈了!

我先用 time 命令测了下原始耗时:

time npm run lint
# real    0m4.872s

接近5秒,确实离谱。然后我翻了下 ESLint 官方文档,发现它有个 --debug 模式,能输出详细执行过程。一跑,好家伙,光是加载插件和解析配置就花了1.2秒,而真正 lint 文件的时间反而没那么长。

更关键的是,我发现它居然在扫描 node_modulesdist 目录!虽然我们在 .eslintignore 里写了忽略,但 ESLint 默认还是会先读取这些目录的文件列表,再过滤——白白浪费时间。

另外,项目里用了 @typescript-eslint/parser,但没配缓存,每次都要重新解析整个 TS 项目,开销巨大。

核心优化:三招搞定

折腾了半天,最后靠这三招把时间压到800ms以内,亲测有效。

1. 明确指定 files,别让 ESLint 自己猜

以前我们的脚本是这样写的:

{
  "scripts": {
    "lint": "eslint ."
  }
}

这个 . 太模糊了,ESLint 会递归遍历所有子目录,哪怕你 ignore 了,前期扫描也逃不掉。改成只扫描需要的文件类型:

{
  "scripts": {
    "lint": "eslint "src/**/*.{js,jsx,ts,tsx}""
  }
}

注意引号要转义,不然 shell 会提前展开。这一改,直接省了600ms,因为不再碰 node_modulespublicbuild 这些目录了。

2. 开启 cache,别重复劳动

TypeScript 项目最耗时的就是类型解析。ESLint 本身支持缓存,但默认关闭。加上 --cache 就行:

{
  "scripts": {
    "lint": "eslint "src/**/*.{js,jsx,ts,tsx}" --cache"
  }
}

第一次跑还是慢,但后续只要文件没变,就直接读缓存。实测第二次跑从4.8s降到1.1s。

这里注意我踩过好几次坑:缓存默认存在 .eslintcache,但如果你用的是 monorepo,最好指定路径,避免冲突。比如:

{
  "lint": "eslint ... --cache --cache-location ./.cache/eslint/"
}

3. 精简配置,砍掉无用规则

打开 .eslintrc.js,发现里面塞了快80条规则,很多是团队早期为了“规范”硬加的,比如强制函数注释、禁止 console(但 dev 环境又手动关掉)。这些规则不仅增加解析负担,还拖慢执行。

我干了两件事:

  • 移除所有非必要的 strict 规则,比如 require-jsdocno-inline-comments
  • extends['airbnb', 'prettier', 'plugin:react/recommended'] 简化成只保留真正用到的部分

优化后的配置核心部分长这样:

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
    tsconfigRootDir: __dirname,
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
  ],
  rules: {
    // 只保留我们真正在意的几条
    '@typescript-eslint/no-explicit-any': 'warn',
    'react/react-in-jsx-scope': 'off',
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
  },
  ignorePatterns: ['node_modules/', 'dist/', 'build/'],
};

特别注意:别同时用 airbnbprettier 的完整 preset,它们有大量重叠规则,ESLint 要做额外合并计算,很耗时。我们后来干脆用 Prettier 单独格式化,ESLint 只管逻辑错误。

性能数据对比

优化前后,我在同一台 MacBook Pro (M1) 上跑了5次取平均值:

场景 平均耗时 降低幅度
优化前(首次) 4870ms
优化后(首次) 1210ms 75%
优化后(带缓存) 780ms 84%

编辑器体验提升最明显:以前保存文件要等2秒才出红波浪线,现在基本实时反馈。CI 流水线也快了不少,lint 步骤从15秒缩到3秒。

还有一些小细节

除了上面三大招,我还顺手做了几件小事:

  • .eslintignore 里的路径写绝对点,比如 **/node_modules 改成 node_modules/,减少 glob 匹配开销
  • 升级 ESLint 到 v8+,新版解析器性能有提升
  • 在 VS Code 里关掉 “Auto Fix On Save” 对非 JS/TS 文件的监听,避免误触发

不过有个小问题没彻底解决:如果 TS 项目结构特别复杂(比如有很多 path alias),parser 还是会慢一点。但影响不大,毕竟日常开发主要改局部文件,缓存能 cover 住。

最后说两句

其实 ESLint 性能问题,80% 都出在配置太“全”、扫描范围太广、没开缓存这三点上。别迷信那些“一套配置走天下”的模板,根据项目实际情况裁剪才是王道。

以上是我个人对 ESLint 配置性能优化的完整实践,改完后团队都说“终于不卡了”。如果你有更好的方案,或者遇到类似问题,欢迎评论区交流——毕竟谁也不想在等 linter 的时候刷三次朋友圈吧。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论